Network upgrade notice: Blocknet plans a network upgrade around 2027-02-16. After it, you will have 1 year to move your coins to the new format, until about 2028-02-16. Coins not moved by then cannot be spent. The wallet will guide you. JSON API for the Blocknet privacy blockchain daemon. The API starts when the core runs with `--api <addr>`. Private endpoints require Bearer token authentication with the token in `<dataDir>/api.cookie`, written on startup. Public blockchain routes (`GET /api/health`, `/api/status`, `/api/block/{id}`, `/api/tx/{hash}`, `/api/mempool`, `/api/mempool/txs`, `/api/peers`, `/api/peers/banned`, `/api/stats`, and `POST /api/verify`, `/api/verify-proof`) need no token. Node settings are read and changed with `GET` and `PATCH /api/settings`.
Token read from `<dataDir>/api.cookie`. Generated fresh on every daemon startup using `crypto/rand` (32 bytes, hex-encoded = 64 chars). File has 0600 permissions. Deleted on graceful shutdown.
curl -H "Authorization: Bearer $(cat data/api.cookie)" http://127.0.0.1:8332/api/status
Daemon and node status
Returns the settings saved in <dataDir>/settings.json and the saved settings that wait for a restart. Requires Bearer token.
unauthorized{
"error": "settings unavailable"
}Changes only the fields in the body and saves them to <dataDir>/settings.json. A field set to null goes back to its default. Live fields apply at once. The others are listed in restart_required. Unknown fields are rejected. Requires Bearer token.
{
"explorer_addr": "127.0.0.1:8080",
"save_checkpoints": true
}
unauthorized{
"error": "internal error"
}{
"error": "settings unavailable"
}Lightweight liveness probe. Returns 200 with the current server timestamp. Does not require authentication.
{
"status": "ok",
"timestamp": "2026-03-11T18:30:00Z"
}
Returns node and chain status including peer count, chain height, sync state, mempool summary, and wallet diagnostics (if unlocked).
{
"pid": 4182,
"peer_id": "12D3KooWBLUPjZgAoizTkbNJvHxgHkb2tF1saUhmKBzFfo8zZLfj",
"peers": 8,
"chain_height": 14207,
"best_hash": "0000c3a5b7e2d1f4",
"total_work": 14208,
"mempool_size": 3,
"mempool_bytes": 4821,
"syncing": false,
"identity_age": "2h34m12s",
"peer_addrs": [
"/ip4/203.0.113.7/tcp/28080/p2p/12D3KooWBLUPjZgAoizTkbNJvHxgHkb2tF1saUhmKBzFfo8zZLfj"
],
"wallet": {
"data_version": 1,
"enc_format": "v1",
"kdf_version": 1,
"kdf_memory_mib": 256,
"kdf_iterations": 3,
"kdf_threads": 4,
"created_at": 1710000000,
"view_only": false,
"has_mnemonic": true,
"address_format": "checksummed",
"file_size_bytes": 2048,
"synced_height": 14200
},
"mempool_generation": 17,
"network_upgrade": {
"date": "2027-02-16",
"migration_deadline": "2028-02-16",
"notice": "Blocknet plans a network upgrade around 2027-02-16. After it, you will have 1 year to move your coins to the new format, until about 2028-02-16. Coins not moved by then cannot be spent. The wallet will guide you."
}
}
Verifies a Schnorr signature (Ristretto255) against a Blocknet stealth address. Does not require a wallet — uses only stateless cryptographic verification. Useful for 'login with Blocknet' flows where any node can validate a signature produced by `POST /api/wallet/sign`. Rate-limited per IP.
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"message": "blocknet-auth:1:blocknet.id:a1b2c3d4e5f6:1708531200",
"signature": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}
{
"valid": true
}
{
"valid": false
}
{
"error": "invalid address"
}{
"error": "invalid signature: must be 64 bytes hex-encoded"
}{
"error": "message is required"
}{
"error": "verify rate limit exceeded"
}Returns chain, network, and emission/economics statistics as numeric JSON. All amounts are in atomic units (smallest units). Values are a deterministic function of the chain tip and require no wallet.
{
"height": 5000,
"difficulty": 150000,
"network_hashrate": 500.0,
"avg_block_time": 300.0,
"block_reward": 72325093035,
"emitted": 361625465175000,
"remaining": 9638374534825000,
"target_supply": 10000000000000000,
"pct_emitted": 3.61625465175,
"tail_emission": 200000000,
"months_to_tail": 48,
"blocks_per_month": 8640,
"block_interval_sec": 300
}
Verifies a sender's payment proof. Given a transaction id, the deterministic transaction private key (`tx_key` from `POST /api/wallet/prove`), and a recipient address, confirms the `tx_key` genuinely belongs to the transaction (`valid`) and reveals which of its outputs that address received, with amounts (atomic units) and any memo. Stateless — no wallet required. Rate-limited per IP.
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"tx_key": "f0e1d2c3b4a5968778695a4b3c2d1e0ff0e1d2c3b4a5968778695a4b3c2d1e0f",
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF"
}
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"valid": true,
"total_matched": 250000000,
"outputs": [
{
"index": 0,
"match": true,
"amount": 250000000,
"memo": "invoice 4821"
},
{
"index": 1,
"match": false
}
]
}
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"valid": false,
"total_matched": 0,
"outputs": []
}
{
"error": "txid must be 64 hex characters"
}{
"error": "invalid address"
}{
"error": "transaction not found"
}{
"error": "verify-proof rate limit exceeded"
}Block, transaction, and mempool queries
Returns a block by numeric height or 64-character hex hash. Includes transaction summaries and confirmation count.
{
"height": 14207,
"hash": "0000c3a5b7e2d1f489a1bc37e5d204f8c612aa9b33e7f04d12b8a9e6c7f50321",
"prev_hash": "0000a1f38e2bc9d7a436ef21c87b3d4e59a0f1b267e3c9d58a2b41f6e7083c19",
"merkle_root": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"timestamp": 1738800120,
"difficulty": 100000,
"nonce": 847291,
"tx_count": 2,
"transactions": [
{
"hash": "c7f2e1d3a4b596870123456789abcdef0123456789abcdef0123456789abcdef",
"is_coinbase": true,
"inputs": 0,
"outputs": 1,
"fee": 0
},
{
"hash": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"is_coinbase": false,
"inputs": 1,
"outputs": 2,
"fee": 15000
}
],
"confirmations": 1,
"reward": 72325093035
}
{
"error": "id must be a height or 64-char hex hash"
}{
"error": "block not found"
}Searches mempool first (fast), then the transaction index (a chain scan is used only while the index is still building). Returns the transaction with confirmation count and mempool status.
{
"tx": {
"version": 1,
"inputs": [
{
"key_image": [206,194,102,91,117,127,68,44,128,196,45,250,102,215,110,191,198,108,77,236,91,173,42,44,240,161,206,21,137,3,217,104],
"ring_members": [
[226,131,206,64,181,243,28,67,77,209,63,49,60,73,151,89,90,209,74,106,163,255,119,131,60,185,95,37,147,5,24,172],
[110,193,204,172,204,197,212,189,47,92,19,190,204,227,117,159,115,159,54,160,111,127,196,151,224,41,224,215,131,35,150,164]
],
"ring_commitments": [
[244,65,131,220,148,209,81,144,194,225,99,194,172,101,176,2,181,151,98,87,133,213,118,209,176,204,1,57,103,0,158,85],
[227,105,135,213,239,147,102,10,53,157,38,16,29,213,153,189,151,99,51,202,204,88,135,235,168,65,66,228,199,214,91,184]
],
"pseudo_output": [185,41,236,101,236,26,183,66,110,82,226,90,90,18,56,11,87,242,214,41,217,44,73,158,2,195,168,69,207,102,28,108],
"ring_signature": "gGqM7cNe9fNWJnrrBzqo/CSrAowGo9OFVEUYyxIYr3WVUeAd1XVgO/hXi426JGVYtSk6QEZMLBDCVbV2Uq4br99gnVs4S/4GdsAxeOMpUlXjv4GgF8sKmVFDBZKXlD/8"
}
],
"outputs": [
{
"commitment": [57,12,140,125,114,71,52,44,216,16,15,47,111,119,13,101,214,112,229,142,3,81,216,174,142,79,110,172,52,47,194,49],
"public_key": [183,176,135,22,235,63,193,40,150,185,98,35,23,116,148,40,119,51,194,142,232,186,83,189,181,107,136,36,87,125,83,236],
"range_proof": "UTfDE/BxZuuznHRyDGLMqI4jjrPMqQ47hVuHEzfesKDfO8VhghbfAGS63COpoD+ZntGnzpdBYtfCWZrPAJuSa9yk7uLibfJWK5GrL3iec2VLDBd98yXp1GPE/cx8SwI22XBa7Rl/PulE7aLi2uRR8+aEfo34eozhJ5J4i6ujKUZNdsRObSDU0Knu1B9p18cKwvQDtJjH1nD5cIvf+A7HrM9U70ENyQ0q20XsXRmFwqds6Keswo7XgSnwCRqzciMUD35mCk56QPI6b+6DvFU6U583DZ/Ay2UmfDSaPRWx270jrgbX+jbduetO3lqK9+7fiaV9LI7mfO3CrA79pl35bLWEro+NBWEre9D6e/P75QgvlnHPfJy88rDZqbToipyAdj1ioT1eYm73jZAzY5d0uFuaB0CMFxuVQPs0BpHw9eGuXhqB9DohzfslG01Mmyt/PNVzwubimNucHjJqbIcpUHpYJlAB0ebwlRB2k5DoJHeHZdk6c0yISCQeVJ2T4D/vm86L/OApFN2lgA0udQqJFFnw4o5c3/su8LLRqqQ1UqjS/ZPNEugtoYGlO84A7NMbYLn/4hpoiEOT4Pg+DnpRnwfQL3M67DxO/5WL1PfxfOlKxGFFI43UrogBkJj6TOT3sKrB6aRgesR30hai8sPFTf0SQKkz4TPpB0nRTybwh63LKajCovkSI3iTdC7eMjPjVZkOF6Yclre/3Ep90lxXWSjDe/5JduyC64IE7pNQJeKwmdmA6ZplxPc2ecO3l5cLyowEGf6SdbRwYYBGMRSe4RG6Qy6Xp9RZZkO7i1SD9petOu8mSHPLuy7KB4c/6LyGw743d/EMp3Eg7ZrRO0cXE5v8OzF4RcbovdZP1DL60I8QvW/j43i5Mry3H8uNYT7o",
"encrypted_amount": [81,216,32,197,195,239,128,5],
"encrypted_memo": [58,136,174,57,150,222,80,232,1,134,91,54,152,101,78,191,82,0,165,250,9,57,185,157,122,29,123,40,43,248,35,64,65,243,84,135,216,108,102,159,204,191,224,231,61,126,115,32,173,10,117,112,3,36,30,117,34,16,169,36,121,142,248,109,67,242,124,242,208,97,48,49,220,181,216,210,239,27,50,31,206,173,55,127,98,97,229,71,216,93,142,236,127,38,226,50,25,7,47,121,85,208,248,246,109,205,30,84,194,1,199,135,232,146,216,249,79,97,151,111,29,31,160,29,25,244,80,29]
}
],
"fee": 15000,
"tx_public_key": [194,138,112,166,28,117,16,161,205,137,33,108,161,108,255,202,234,73,135,71,126,134,219,204,185,112,70,252,46,24,56,78]
},
"block_height": 14205,
"confirmations": 3,
"in_mempool": false
}
{
"tx": {
"version": 1,
"inputs": [
{
"key_image": [206,194,102,91,117,127,68,44,128,196,45,250,102,215,110,191,198,108,77,236,91,173,42,44,240,161,206,21,137,3,217,104],
"ring_members": [
[226,131,206,64,181,243,28,67,77,209,63,49,60,73,151,89,90,209,74,106,163,255,119,131,60,185,95,37,147,5,24,172],
[110,193,204,172,204,197,212,189,47,92,19,190,204,227,117,159,115,159,54,160,111,127,196,151,224,41,224,215,131,35,150,164]
],
"ring_commitments": [
[244,65,131,220,148,209,81,144,194,225,99,194,172,101,176,2,181,151,98,87,133,213,118,209,176,204,1,57,103,0,158,85],
[227,105,135,213,239,147,102,10,53,157,38,16,29,213,153,189,151,99,51,202,204,88,135,235,168,65,66,228,199,214,91,184]
],
"pseudo_output": [185,41,236,101,236,26,183,66,110,82,226,90,90,18,56,11,87,242,214,41,217,44,73,158,2,195,168,69,207,102,28,108],
"ring_signature": "gGqM7cNe9fNWJnrrBzqo/CSrAowGo9OFVEUYyxIYr3WVUeAd1XVgO/hXi426JGVYtSk6QEZMLBDCVbV2Uq4br99gnVs4S/4GdsAxeOMpUlXjv4GgF8sKmVFDBZKXlD/8"
}
],
"outputs": [
{
"commitment": [57,12,140,125,114,71,52,44,216,16,15,47,111,119,13,101,214,112,229,142,3,81,216,174,142,79,110,172,52,47,194,49],
"public_key": [183,176,135,22,235,63,193,40,150,185,98,35,23,116,148,40,119,51,194,142,232,186,83,189,181,107,136,36,87,125,83,236],
"range_proof": "UTfDE/BxZuuznHRyDGLMqI4jjrPMqQ47hVuHEzfesKDfO8VhghbfAGS63COpoD+ZntGnzpdBYtfCWZrPAJuSa9yk7uLibfJWK5GrL3iec2VLDBd98yXp1GPE/cx8SwI22XBa7Rl/PulE7aLi2uRR8+aEfo34eozhJ5J4i6ujKUZNdsRObSDU0Knu1B9p18cKwvQDtJjH1nD5cIvf+A7HrM9U70ENyQ0q20XsXRmFwqds6Keswo7XgSnwCRqzciMUD35mCk56QPI6b+6DvFU6U583DZ/Ay2UmfDSaPRWx270jrgbX+jbduetO3lqK9+7fiaV9LI7mfO3CrA79pl35bLWEro+NBWEre9D6e/P75QgvlnHPfJy88rDZqbToipyAdj1ioT1eYm73jZAzY5d0uFuaB0CMFxuVQPs0BpHw9eGuXhqB9DohzfslG01Mmyt/PNVzwubimNucHjJqbIcpUHpYJlAB0ebwlRB2k5DoJHeHZdk6c0yISCQeVJ2T4D/vm86L/OApFN2lgA0udQqJFFnw4o5c3/su8LLRqqQ1UqjS/ZPNEugtoYGlO84A7NMbYLn/4hpoiEOT4Pg+DnpRnwfQL3M67DxO/5WL1PfxfOlKxGFFI43UrogBkJj6TOT3sKrB6aRgesR30hai8sPFTf0SQKkz4TPpB0nRTybwh63LKajCovkSI3iTdC7eMjPjVZkOF6Yclre/3Ep90lxXWSjDe/5JduyC64IE7pNQJeKwmdmA6ZplxPc2ecO3l5cLyowEGf6SdbRwYYBGMRSe4RG6Qy6Xp9RZZkO7i1SD9petOu8mSHPLuy7KB4c/6LyGw743d/EMp3Eg7ZrRO0cXE5v8OzF4RcbovdZP1DL60I8QvW/j43i5Mry3H8uNYT7o",
"encrypted_amount": [81,216,32,197,195,239,128,5],
"encrypted_memo": [58,136,174,57,150,222,80,232,1,134,91,54,152,101,78,191,82,0,165,250,9,57,185,157,122,29,123,40,43,248,35,64,65,243,84,135,216,108,102,159,204,191,224,231,61,126,115,32,173,10,117,112,3,36,30,117,34,16,169,36,121,142,248,109,67,242,124,242,208,97,48,49,220,181,216,210,239,27,50,31,206,173,55,127,98,97,229,71,216,93,142,236,127,38,226,50,25,7,47,121,85,208,248,246,109,205,30,84,194,1,199,135,232,146,216,249,79,97,151,111,29,31,160,29,25,244,80,29]
}
],
"fee": 12000,
"tx_public_key": [194,138,112,166,28,117,16,161,205,137,33,108,161,108,255,202,234,73,135,71,126,134,219,204,185,112,70,252,46,24,56,78]
},
"confirmations": 0,
"in_mempool": true
}
{
"error": "hash must be 64 hex characters"
}{
"error": "transaction not found"
}Returns mempool transaction count, total size in bytes, and fee statistics (min, max, average) in atomic units.
{
"count": 5,
"size_bytes": 8420,
"generation": 42,
"min_fee": 10000,
"max_fee": 25000,
"avg_fee": 14600.0
}
Returns all currently unconfirmed mempool transactions as full transaction objects in a JSON array. Each item matches the same `Transaction` schema returned by `GET /api/tx/{hash}`. Returns an empty array when the mempool is empty.
[
{
"version": 1,
"inputs": [
{
"key_image": [206,194,102,91,117,127,68,44,128,196,45,250,102,215,110,191,198,108,77,236,91,173,42,44,240,161,206,21,137,3,217,104],
"ring_members": [
[226,131,206,64,181,243,28,67,77,209,63,49,60,73,151,89,90,209,74,106,163,255,119,131,60,185,95,37,147,5,24,172],
[110,193,204,172,204,197,212,189,47,92,19,190,204,227,117,159,115,159,54,160,111,127,196,151,224,41,224,215,131,35,150,164]
],
"ring_commitments": [
[244,65,131,220,148,209,81,144,194,225,99,194,172,101,176,2,181,151,98,87,133,213,118,209,176,204,1,57,103,0,158,85],
[227,105,135,213,239,147,102,10,53,157,38,16,29,213,153,189,151,99,51,202,204,88,135,235,168,65,66,228,199,214,91,184]
],
"pseudo_output": [185,41,236,101,236,26,183,66,110,82,226,90,90,18,56,11,87,242,214,41,217,44,73,158,2,195,168,69,207,102,28,108],
"ring_signature": "gGqM7cNe9fNWJnrrBzqo/CSrAowGo9OFVEUYyxIYr3WVUeAd1XVgO/hXi426JGVYtSk6QEZMLBDCVbV2Uq4br99gnVs4S/4GdsAxeOMpUlXjv4GgF8sKmVFDBZKXlD/8"
}
],
"outputs": [
{
"commitment": [57,12,140,125,114,71,52,44,216,16,15,47,111,119,13,101,214,112,229,142,3,81,216,174,142,79,110,172,52,47,194,49],
"public_key": [183,176,135,22,235,63,193,40,150,185,98,35,23,116,148,40,119,51,194,142,232,186,83,189,181,107,136,36,87,125,83,236],
"encrypted_amount": [81,216,32,197,195,239,128,5],
"encrypted_memo": [58,136,174,57,150,222,80,232,1,134,91,54,152,101,78,191,82,0,165,250,9,57,185,157,122,29,123,40,43,248,35,64,65,243,84,135,216,108,102,159,204,191,224,231,61,126,115,32,173,10,117,112,3,36,30,117,34,16,169,36,121,142,248,109,67,242,124,242,208,97,48,49,220,181,216,210,239,27,50,31,206,173,55,127,98,97,229,71,216,93,142,236,127,38,226,50,25,7,47,121,85,208,248,246,109,205,30,84,194,1,199,135,232,146,216,249,79,97,151,111,29,31,160,29,25,244,80,29]
}
],
"fee": 12000,
"tx_public_key": [194,138,112,166,28,117,16,161,205,137,33,108,161,108,255,202,234,73,135,71,126,134,219,204,185,112,70,252,46,24,56,78]
}
]
[]
Appends checkpoints (block height + hash, every 100 blocks) to `<dataDir>/checkpoints.dat`, resuming after the last one already written. Only finalized heights are written: up to the chain tip minus 100 blocks, rounded down to a multiple of 100. If no height is final yet, it writes nothing and returns `message: "chain is empty, nothing to save"`. Checkpoints let nodes fast-sync by skipping proof-of-work re-verification at or below the checkpointed height. Requires Bearer token.
{
"written": 3,
"chain_height": 14207,
"last_checkpoint": 14200,
"path": "/home/user/.blocknet/checkpoints.dat"
}
unauthorized{
"error": "failed to create data dir"
}{
"error": "failed to open checkpoints file"
}{
"error": "failed to write checkpoint"
}Downloads the checkpoints file if not present, loads it, and registers the checkpoints as trusted so blocks at or below the maximum checkpoint height can skip proof-of-work re-verification during sync. Requires Bearer token.
{
"downloaded": true,
"loaded": 142,
"max_height": 14200,
"chain_height": 5000,
"fast_sync": true
}
unauthorized{
"error": "failed to load checkpoints"
}{
"error": "failed to fetch checkpoints"
}Walks the entire chain and checks every block's difficulty (LWMA), timestamp rules, and prev-hash linkage. This is an arithmetic-only check (no Argon2id PoW re-hashing), so it completes in seconds. Returns all violations found, or confirms the chain is clean.
{
"height": 14207,
"clean": true
}
{
"height": 14207,
"clean": false,
"violations": [
{
"height": 8042,
"message": "difficulty mismatch: stored 5678, expected 1234"
},
{
"height": 8043,
"message": "timestamp 1708531200 <= median 1708531260"
}
]
}
unauthorizedPeer connectivity and ban management
Returns the list of currently connected libp2p peers with their peer IDs and remote multiaddrs.
{
"count": 3,
"peers": [
{
"peer_id": "12D3KooWBLUPjZgAoizTkbNJvHxgHkb2tF1saUhmKBzFfo8zZLfj",
"addrs": [
"/ip4/203.0.113.10/tcp/28080"
]
},
{
"peer_id": "12D3KooWN7z3vEqr4C8pMk2axGfRbLVJzqPEasiY4L9DMqFjVnGq",
"addrs": [
"/ip4/198.51.100.22/tcp/28080"
]
},
{
"peer_id": "12D3KooWQe1RkTvGvbFYm6G3bNzdpJRcmAQA4f9bUDkYcFWLdM4P",
"addrs": [
"/ip4/192.0.2.5/tcp/28080"
]
}
]
}
Returns the list of banned peers with ban reason, count, permanence, and expiry time.
{
"count": 2,
"banned": [
{
"peer_id": "12D3KooWMalicious111111111111111111111111111111111111",
"addrs": [
"/ip4/203.0.113.50/tcp/28080"
],
"reason": "sent invalid block",
"ban_count": 3,
"permanent": false,
"expires_at": "2026-02-06T19:30:00Z"
},
{
"peer_id": "12D3KooWMalicious222222222222222222222222222222222222",
"addrs": [
"/ip4/198.51.100.99/tcp/28080"
],
"reason": "excessive invalid transactions",
"ban_count": 5,
"permanent": true
}
]
}
Balance, address, history, and sending. The node always starts without a wallet. Call `POST /api/wallet/load`, `/api/wallet/create` or `/api/wallet/import` first. Wallet files live in the folder of the `wallet_file` setting. Most other wallet endpoints need a loaded, unlocked wallet. `lock`, `unlock`, `send/status` and `send/advanced/status` do not need it unlocked.
Loads an existing wallet from disk, decrypting with the given password. The node always starts without a wallet, so a client calls this (or create/import) first. If `filepath` is provided, only the basename is used and the file is resolved in the folder of the `wallet_file` setting; if omitted, `wallet_file` itself is loaded. After loading, the wallet is unlocked, all wallet endpoints become available, and miner reward keys are pointed at this wallet. If blocks arrived while the wallet was offline, a background scan is started automatically — check `synced_height` vs `chain_height` in the response or the balance endpoint to track progress. Returns 409 while a wallet is loaded or another load is running. After `POST /api/wallet/unload` it can be called again.
{
"password": "my-wallet-passphrase",
"filepath": "mywallet.dat"
}
{
"loaded": true,
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"filename": "mywallet.dat",
"synced_height": 4200,
"chain_height": 9800
}
{
"error": "invalid JSON body"
}{
"error": "password must be at least 3 characters"
}{
"error": "invalid filepath"
}{
"error": "wrong password"
}unauthorized{
"error": "wallet file not readable (permission denied)"
}{
"error": "wallet file not found"
}{
"error": "wallet already loaded"
}{
"error": "wallet file is corrupted"
}{
"error": "internal error"
}Generates a new wallet with a fresh BIP39 seed, encrypts it with the given password, and saves it to disk. The wallet is loaded and unlocked in the running daemon. Since this is a brand-new wallet, no chain scanning is needed — the synced height is set to the current chain tip. Can only be called when no wallet is currently loaded (returns 409 otherwise). If `filename` is provided, only the basename is used and the file is placed in the folder of the `wallet_file` setting; if omitted, `wallet_file` itself is used. Will not overwrite an existing file.
{
"password": "my-wallet-passphrase"
}
{
"created": true,
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"filename": "wallet.dat"
}
{
"error": "invalid JSON body"
}{
"error": "password must be at least 3 characters"
}{
"error": "invalid filename"
}unauthorized{
"error": "wallet already loaded"
}{
"error": "wallet file already exists: wallet.dat"
}{
"error": "internal error"
}Locks and unloads the currently loaded wallet, releasing all in-memory key material. After this call the node returns to the same state as before load was called — wallet endpoints that need a wallet return 503 until one is loaded again with load, create or import. Mining reward keys are cleared. No request body required.
{
"unloaded": true
}
unauthorized{
"error": "no wallet loaded"
}Creates a new wallet from exactly one source: a BIP39 12-word recovery seed (`mnemonic`), hex private keys (`spend_priv` + `view_priv`), or a view-only key pair (`spend_pub` + `view_priv`, which makes a wallet that can watch but not spend). It encrypts it with the given password, and saves it to disk. The wallet is loaded and unlocked in the running daemon and a background scan of the entire blockchain is started to find outputs belonging to this seed. Check `synced_height` vs `chain_height` in the response or the balance endpoint to track progress. Can only be called when no wallet is currently loaded (returns 409 otherwise). If `filename` is provided, only the basename is used and the file is placed in the same directory as the folder of the `wallet_file` setting; if omitted, the default wallet path is used. Will not overwrite an existing file.
{
"mnemonic": "abandon ability able about above absent absorb abstract absurd abuse access accident",
"password": "my-wallet-passphrase",
"filename": "restored.dat"
}
{
"imported": true,
"view_only": false,
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"filename": "restored.dat",
"synced_height": 0,
"chain_height": 9800
}
{
"error": "invalid JSON body"
}{
"error": "provide exactly one of: mnemonic, spend_priv + view_priv, or spend_pub + view_priv (view-only)"
}{
"error": "invalid mnemonic phrase"
}{
"error": "invalid spend_priv: expected 64 hex chars"
}{
"error": "password must be at least 3 characters"
}{
"error": "invalid filename"
}unauthorized{
"error": "wallet already loaded"
}{
"error": "wallet file already exists: restored.dat"
}{
"error": "internal error"
}Returns spendable, pending, and total confirmed balance in atomic units (1 BNT = 100,000,000 atomic units). Spendable counts only mature outputs: coinbase outputs need coinbase maturity, and regular outputs need 10 confirmations. Also includes an optional UX-only `pending_unconfirmed` amount (typically change from your most recent send) plus an estimated unlock ETA in seconds, assuming ~5 minute blocks. If the wallet is more than 100 blocks behind the chain (background scan in progress), balance numbers are omitted and `scanning: true` is returned with progress info instead. Requires unlocked wallet.
{
"spendable": 1250000000,
"pending": 72325093035,
"pending_unconfirmed": 0,
"pending_unconfirmed_eta": 0,
"total": 73575093035,
"outputs_total": 14,
"outputs_unspent": 9,
"chain_height": 14207,
"scanning": false,
"synced_height": 14207,
"memo_decrypt_failures": 0,
"memo_decrypt_last_height": 0
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Returns the wallet's public stealth address (base58 of spend_pub || view_pub || 4-byte checksum, 68 bytes). Senders derive unique one-time addresses from this. Requires unlocked wallet.
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"view_only": false
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Returns every wallet output, spent and immature ones included, with amounts, block heights, coinbase flag, and spent status. Requires unlocked wallet.
{
"count": 3,
"outputs": [
{
"txid": "c7f2e1d3a4b596870123456789abcdef0123456789abcdef0123456789abcdef",
"output_index": 0,
"amount": 72325093035,
"block_height": 14200,
"is_coinbase": true,
"spent": false
},
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"output_index": 0,
"amount": 500000000,
"block_height": 14100,
"is_coinbase": false,
"spent": false
},
{
"txid": "f0e1d2c3b4a5968778695a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d",
"output_index": 1,
"amount": 750000000,
"block_height": 13990,
"is_coinbase": false,
"spent": true,
"spent_height": 14050
}
]
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Same wallet outputs as GET /api/wallet/history, but returned newest-first in deterministic pages so busy wallets do not have to ship their entire output set at once. Ordering is stable across pages: pending outputs (block_height 0) first, then descending block height, then txid, then output index. Page with limit/offset and use the total field to know when to stop. The unpaginated /api/wallet/history endpoint remains available and unchanged. Requires unlocked wallet.
{
"count": 2,
"total": 4213,
"limit": 20,
"offset": 0,
"order": "desc",
"outputs": [
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"output_index": 0,
"amount": 500000000,
"block_height": 14100,
"is_coinbase": false,
"spent": false
},
{
"txid": "f0e1d2c3b4a5968778695a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d",
"output_index": 1,
"amount": 750000000,
"block_height": 13990,
"is_coinbase": false,
"spent": true,
"spent_height": 14050
}
]
}
{
"error": "order must be asc or desc"
}unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Returns outbound payments recorded by the loaded wallet. This is wallet-local send metadata: recipient addresses and memos are available because the wallet recorded them at send time. Chain lookup is used only to annotate each tx as confirmed, mempool, or not_found. Requires unlocked wallet.
{
"count": 1,
"total": 18,
"limit": 50,
"offset": 0,
"order": "desc",
"sends": [
{
"txid": "b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4",
"timestamp": 1778085481,
"recorded_height": 21091,
"chain_state": "confirmed",
"confirmations": 8,
"in_mempool": false,
"fee": 5698010,
"total_amount": 3250000000000,
"recipients": [
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"amount": 3250000000000,
"memo_hex": "696e766f696365202338343231"
}
]
}
]
}
{
"error": "order must be asc or desc"
}unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Returns every output owned by the wallet with computed status (spent/unspent/pending), confirmations, type, cryptographic keys, and summary counts. Sorted ascending by block height, then txid, then output index. Requires unlocked wallet.
{
"chain_height": 14207,
"synced_height": 14207,
"total": 3,
"spent": 1,
"unspent": 1,
"pending": 1,
"outputs": [
{
"txid": "f0e1d2c3b4a5968778695a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d",
"output_index": 1,
"amount": 750000000,
"status": "spent",
"type": "regular",
"confirmations": 217,
"block_height": 13990,
"spent_height": 14050,
"one_time_pub": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"commitment": "c7f2e1d3a4b596870123456789abcdef0123456789abcdef0123456789abcdef"
},
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"output_index": 0,
"amount": 500000000,
"status": "unspent",
"type": "regular",
"confirmations": 107,
"block_height": 14100,
"one_time_pub": "d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5",
"commitment": "e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6"
},
{
"txid": "c7f2e1d3a4b596870123456789abcdef0123456789abcdef0123456789abcdef",
"output_index": 0,
"amount": 72325093035,
"status": "pending",
"type": "coinbase",
"confirmations": 7,
"block_height": 14200,
"one_time_pub": "b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9",
"commitment": "f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7"
}
]
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Builds a privacy-preserving transaction with one or more recipients using RingCT (Pedersen commitments, Bulletproofs range proofs, CLSAG ring signatures with fixed ring size 16), submits to mempool, and broadcasts via Dandelion++. Fee is calculated as max(min_fee, fee_per_byte * tx_size). Note: multi-recipient transactions link all recipients within the same transaction from a graph-analysis perspective. Requires unlocked full wallet (not view-only).
{
"recipients": [
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"amount": 500000000
}
]
}
{
"txid": "b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4",
"fee": 15000,
"change": 734850000,
"recipients": [
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"amount": 500000000
}
],
"dry_run": false
}
{
"error": "recipient 0: invalid address"
}{
"error": "recipient 0: amount must be greater than 0"
}{
"error": "insufficient spendable balance: have 2.5 BNT, need 5 BNT"
}{
"error": "insufficient spendable balance: have 2.5 BNT spendable + 3 BNT pending (confirming), need 5 BNT"
}{
"error": "idempotency key too long"
}unauthorized{
"error": "wallet is locked"
}{
"error": "view-only wallet cannot send"
}{
"error": "idempotency key reuse with different request"
}{
"error": "idempotency key in progress"
}{
"error": "mempool rejected: double-spend: key image already in mempool (tx 1a2b3c4d5e6f7a8b...)"
}{
"error": "request was interrupted by a node restart and its outcome is unknown; check GET /api/wallet/sends before sending again with a new idempotency key"
}{
"error": "mempool rejected: mempool full"
}{
"error": "send rate limit exceeded"
}{
"error": "send busy, retry later"
}{
"error": "failed to select ring members: not enough outputs for ring (need 15, have 9)"
}{
"error": "no wallet loaded"
}Returns the persisted status of a previous POST /api/wallet/send request for the provided idempotency key. Unresolved accepted requests survive daemon restart and return state=accepted instead of silently disappearing.
{
"error": "idempotency_key is required"
}unauthorizedBuilds a transaction with one or more recipients using caller-specified inputs (coin control). The caller selects which outputs to spend by referencing txid + output_index pairs from GET /api/wallet/outputs. No automatic input selection is performed. Supports dry_run mode to preview fee and change before broadcasting. Optional change_split (1-4) distributes change across multiple outputs for improved back-to-back send concurrency at the cost of reduced privacy. Same fee calculation, ring signatures, and Dandelion++ broadcast as the standard send endpoint.
{
"txid": "c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
"fee": 15000,
"change": 234850000,
"change_split": 1,
"input_total": 735000000,
"input_count": 2,
"dry_run": false,
"recipients": [
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"amount": 500000000
}
]
}
{
"fee": 15000,
"change": 234850000,
"change_split": 1,
"input_total": 735000000,
"input_count": 1,
"dry_run": true,
"recipients": [
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"amount": 500000000
}
]
}
{
"error": "inputs array is required for coin control"
}{
"error": "input 0: output not found (txid b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, index 0)"
}{
"error": "input 1: immature, has 3 confirmations, needs 10 (txid b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, index 0)"
}{
"error": "input 0: key image already in mempool (txid b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, index 0)"
}{
"error": "input 2: duplicate of input 0 (txid b3c4d5...a2b3c4, index 0)"
}{
"error": "insufficient input amount: inputs total 0.001 BNT, need at least 5.00015 BNT (amount 5 BNT + fee 0.00015 BNT)"
}{
"error": "insufficient funds after fee adjustment: have 0.001 BNT need 5.00015 BNT"
}{
"error": "too many inputs (max 256)"
}{
"error": "input 0: txid must be 64 hex characters"
}{
"error": "input 0: output already spent (txid b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4, index 0)"
}{
"error": "change_split must be 1-4"
}unauthorized{
"error": "wallet is locked"
}{
"error": "view-only wallet cannot send"
}{
"error": "idempotency key reuse with different request"
}{
"error": "idempotency key in progress"
}{
"error": "mempool rejected: double-spend: key image already in mempool (tx 1a2b3c4d5e6f7a8b...)"
}{
"error": "request was interrupted by a node restart and its outcome is unknown; check GET /api/wallet/sends before sending again with a new idempotency key"
}{
"error": "mempool rejected: mempool full"
}{
"error": "send rate limit exceeded"
}{
"error": "send busy, retry later"
}{
"error": "internal error"
}{
"error": "no wallet loaded"
}Returns the persisted status of a previous POST /api/wallet/send/advanced request for the provided idempotency key. This endpoint is intended for payout systems that need to recover the txid after a slow or timed-out send call.
{
"error": "idempotency_key is required"
}unauthorizedSigns an arbitrary message with the wallet's spend private key (Schnorr over Ristretto255). Useful for proving address ownership to external services ('login with Blocknet'). Response includes `Cache-Control: no-store`. Requires unlocked full wallet (not view-only).
{
"message": "blocknet-auth:1:blocknet.id:a1b2c3d4e5f6:1708531200"
}
{
"address": "9PNoFCqUa7K8e5JfV2Hs3TBt7kMzRGkPxJ4xVmn5cFbLd1Qy8W6uXo3Z9pNvRwA2hY7sK4mBjE6gC8dF",
"signature": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"message": "blocknet-auth:1:blocknet.id:a1b2c3d4e5f6:1708531200"
}
{
"error": "message is required"
}{
"error": "message must be <= 1024 bytes"
}unauthorized{
"error": "wallet is locked"
}{
"error": "view-only wallet cannot sign"
}{
"error": "internal error"
}{
"error": "no wallet loaded"
}Locks the wallet. All wallet endpoints (balance, address, history, send) will return 403 until unlocked. No request body required.
{
"locked": true
}
unauthorized{
"error": "no wallet loaded"
}Unlocks the wallet with the wallet password. Uses constant-time comparison (`crypto/subtle.ConstantTimeCompare`) to prevent timing attacks.
{
"password": "my-wallet-passphrase"
}
{
"locked": false
}
{
"error": "invalid JSON body"
}{
"error": "wrong password"
}unauthorized{
"error": "too many unlock attempts; try again later"
}{
"error": "unlock backoff active; retry later"
}{
"error": "no wallet loaded"
}{
"error": "unlock unavailable: password state not initialized"
}Returns the wallet's 12-word BIP39 recovery phrase. Requires Bearer token and wallet password confirmation. Response includes Cache-Control: no-store.
{
"password": "my-wallet-passphrase"
}
{
"mnemonic": "abandon ability able about above absent absorb abstract absurd abuse access accident",
"words": [
"abandon",
"ability",
"able",
"about",
"above",
"absent",
"absorb",
"abstract",
"absurd",
"abuse",
"access",
"accident"
]
}
{
"error": "invalid JSON body"
}{
"error": "incorrect password"
}{
"error": "wallet is locked"
}{
"error": "no recovery seed available"
}{
"error": "too many attempts; try again later"
}{
"error": "attempt backoff active; retry later"
}{
"error": "internal error"
}{
"error": "no wallet loaded"
}{
"error": "seed unavailable: password state not initialized"
}Triggers a background rescan from the wallet's last synced height to the chain tip. Returns immediately with the current sync state. Check the balance endpoint to track progress. Requires loaded, unlocked wallet.
{
"status": "scanning",
"synced_height": 4200,
"chain_height": 9800
}
{
"status": "already synced",
"synced_height": 14207,
"chain_height": 14207
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Derives the deterministic transaction private key to prove a transaction was sent by this wallet. The tx key can be shared with a recipient or third party to verify payment. Works on both full and view-only wallets (uses the view private key). Requires loaded, unlocked wallet. Response includes `Cache-Control: no-store`.
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
}
{
"txid": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"tx_key": "f0e1d2c3b4a5f6e7d8c9b0a1f2e3d4c5b6a7f8e9d0c1b2a3f4e5d6c7b8a9f0e1"
}
{
"error": "txid must be 64 hex characters"
}{
"error": "coinbase transactions have no sender proof"
}unauthorized{
"error": "wallet is locked"
}{
"error": "transaction not found on chain"
}{
"error": "transaction was not sent by this wallet"
}{
"error": "failed to derive tx key"
}{
"error": "no wallet loaded"
}Scans all wallet outputs and groups them by key image. Outputs that share a key image are duplicates caused by a historical self-send key derivation bug — only one output per group can ever be spent, the rest are permanently unspendable (burned). No request body required. Requires loaded, unlocked wallet.
{
"total_outputs": 42,
"unique_key_images": 42,
"failed_key_images": 0,
"duplicate_groups": null,
"total_burned": 0,
"burned_outputs": 0
}
{
"total_outputs": 42,
"unique_key_images": 40,
"failed_key_images": 0,
"duplicate_groups": [
{
"key_image": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"outputs": [
{
"txid": "b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4",
"output_index": 0,
"amount": 500000000,
"spent": false,
"block_height": 1200
},
{
"txid": "c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b3c4d5",
"output_index": 1,
"amount": 100000000,
"spent": false,
"block_height": 1201
}
],
"burned_amount": 100000000,
"unspendable_count": 1
}
],
"total_burned": 100000000,
"burned_outputs": 1
}
unauthorized{
"error": "wallet is locked"
}{
"error": "no wallet loaded"
}Returns the wallet's view-only key material (spend public key, view private key, view public key). These keys allow monitoring incoming funds and transaction history without spending ability. Requires Bearer token and wallet password confirmation. Response includes Cache-Control: no-store. Not available on view-only wallets.
{
"password": "my-wallet-passphrase"
}
{
"spend_pub": "a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2",
"view_priv": "f0e1d2c3b4a5f6e7d8c9b0a1f2e3d4c5b6a7f8e9d0c1b2a3f4e5d6c7b8a9f0e1",
"view_pub": "d4c3b2a1e5f6d7c8b9a0e1f2d3c4b5a6e7f8d9c0b1a2e3f4d5c6b7a8e9f0d1c2"
}
{
"error": "invalid JSON body"
}{
"error": "file_password must be at least 3 characters"
}{
"error": "invalid filename"
}{
"error": "file_password must differ from the wallet password"
}{
"error": "incorrect password"
}{
"error": "wallet is locked"
}{
"error": "this is already a view-only wallet"
}{
"error": "wallet file already exists: main.view.wallet.dat"
}{
"error": "too many attempts; try again later"
}{
"error": "attempt backoff active; retry later"
}{
"error": "failed to create view-only wallet"
}{
"error": "no wallet loaded"
}{
"error": "viewkeys unavailable: password state not initialized"
}Argon2id PoW miner control (~2GB RAM per thread)
Returns mining state, thread count, and stats (hashrate, hash count, blocks found, start time) when running. Hashrate and stat fields are omitted when the miner is stopped.
{
"running": true,
"threads": 4,
"hashrate": 2.37,
"hash_count": 8532,
"blocks_found": 12,
"started_at": "2026-02-06T14:00:00Z"
}
{
"running": false,
"threads": 4
}
unauthorizedStarts the Argon2id proof-of-work miner. Load a wallet first: the miner pays the wallet that was loaded when the core started mining, and with no wallet the coinbase pays throwaway keys and the reward is lost. The miner waits until it has at least one peer. Each thread allocates ~2GB RAM. No request body required.
{
"running": true
}
unauthorized{
"error": "mining already running"
}Stops the miner. No request body required.
{
"running": false
}
unauthorized{
"error": "mining not running"
}Sets the number of mining threads. Each thread uses ~2GB RAM for Argon2id. Takes effect immediately if the miner is running.
{
"threads": 4
}
{
"threads": 4
}
{
"error": "threads must be >= 1"
}unauthorizedReturns a complete block template ready for proof-of-work solving. Includes a pre-built coinbase transaction (paying to the loaded wallet by default, or to the optional `address` override), selected mempool transactions, and the computed merkle root. The `target` field (hex) is the PoW target that the Argon2id hash must be less than. The `header_base` field (hex) is the 92-byte serialized header without the nonce. PoW hash = Argon2id(password = nonce as 8 bytes little-endian, salt = header_base bytes), 32-byte output. The `block` field is the raw consensus form (PascalCase header keys, byte arrays as integer arrays), not the `GET /api/block` summary. The `template_id` field identifies this template and can be used with compact submit payloads (`template_id` + `nonce`) via `POST /api/mining/submitblock`. Its compact-submission lease expires at `template_expires_at_unix_ms`; clients may extend a live, current-tip lease with `POST /api/mining/renewtemplate`. The daemon retains at most 512 live leases for one tip and returns 503 rather than evicting a lease before its advertised expiry. Requires a loaded wallet (for coinbase keys) but does not require it to be unlocked.
{
"block": {
"header": {
"Version": 1,
"Height": 14208,
"PrevHash": [0,0,195,165,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
"MerkleRoot": [171,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
"Timestamp": 1708531200,
"Difficulty": 14208,
"Nonce": 0
},
"transactions": [
{
"version": 1,
"inputs": [],
"outputs": [
{
"commitment": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
"public_key": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
"range_proof": "",
"encrypted_amount": [0,0,0,0,0,0,0,0],
"encrypted_memo": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
}
],
"fee": 0,
"tx_public_key": [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
}
]
},
"target": "0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
"header_base": "0100000080370000...",
"reward_address_used": "3wZc3y1Qw4eYpZtGJxkqkV6xG9c2oXHqfJjQ6b3sR5hYhJ8tZz1qvJ1mY1a9o7hV4pYwqH7xG5d5d8cJ8p4",
"template_id": "7b3d2f4a9d11c8ef",
"template_expires_at_unix_ms": 1738800840000,
"mempool_generation": 17
}
{
"error": "invalid address"
}unauthorized{
"error": "internal error"
}{
"error": "no wallet loaded"
}{
"error": "node is syncing"
}{
"code": "mining_template_tip_changed",
"error": "chain tip changed while building template, retry"
}{
"code": "mining_template_cache_full",
"error": "mining template cache full, retry after a lease expires or the chain tip changes"
}Extends the compact-submission lease of an unexpired cached template. Renewal succeeds only while the template still builds directly on the current canonical chain tip. This does not rebuild or otherwise change the template.
{
"template_id": "7b3d2f4a9d11c8ef"
}
{
"template_id": "7b3d2f4a9d11c8ef",
"template_expires_at_unix_ms": 1738801140000
}
{
"error": "invalid JSON body"
}unauthorized{
"error": "unknown or expired template_id"
}{
"error": "template no longer builds on current tip"
}{
"error": "internal error"
}Accepts a solved block (from pool mining or an external miner). Send either the full block in the raw consensus form (see `RawBlock`, as returned in `GET /api/mining/blocktemplate`) or a compact `template_id` + `nonce`. The block must pass full validation: correct height, prev hash linking to the current tip, valid difficulty, valid Argon2id proof-of-work, valid merkle root, and valid transactions. On success the block is broadcast to peers and `mined_block` subscribers are notified. `accepted: true` is also returned when the block is valid but lands on a side chain. Rate limit: 2 requests/s per IP (burst 4), 2 at a time.
Either a complete block object with a valid nonce, or a compact payload containing `template_id` and `nonce`.
Option: RawBlock
Option: CompactSubmitBlock
{
"accepted": true,
"hash": "0000d4b5a8e7c3f2910b6e5d4c3a2f1e0d9c8b7a6f5e4d3c2b1a09f8e7d6c5b4",
"height": 14208
}
{
"error": "block rejected"
}{
"error": "block rejected as stale"
}{
"error": "invalid JSON body"
}{
"error": "nonce is required with template_id"
}{
"error": "unknown or expired template_id"
}unauthorized{
"error": "submitblock rate limit exceeded"
}{
"error": "submitblock busy, retry later"
}Real-time Server-Sent Events stream for new blocks and mining notifications
Server-Sent Events stream for real-time updates. On connection, emits a `connected` event with current chain state. Then streams `new_block` for every new block added to the chain and `mined_block` for every block accepted through `POST /api/mining/submitblock` or the built-in miner. Sends SSE comment keepalives every 30s. Write timeout is disabled for this long-lived connection.
connectedSent immediately on connection
event: connected
data: {"chain_height":14207,"syncing":false}
new_blockNew block added to chain
event: new_block
data: {"height":14208,"hash":"0000d4b5a8e7c3f2910b6e5d4c3a2f1e0d9c8b7a6f5e4d3c2b1a09f8e7d6c5b4","timestamp":1738800240,"tx_count":3}
mined_blockBlock mined by this node
event: mined_block
data: {"height":14208,"hash":"0000d4b5a8e7c3f2910b6e5d4c3a2f1e0d9c8b7a6f5e4d3c2b1a09f8e7d6c5b4","reward":72325093035}
keepaliveSSE comment sent every 30s to keep connection alive
: keepalive
curl -N -H "Authorization: Bearer $(cat data/api.cookie)" http://127.0.0.1:8332/api/events
unauthorized{
"error": "streaming not supported"
}{
"error": "failed to initialize SSE stream"
}Dangerous administrative operations (data purge, etc.). These are irreversible and require explicit confirmation.
Deletes all blockchain data from disk. Requires explicit confirmation. Stops the daemon, removes the data directory (chain database, checkpoints file, send idempotency records and the API cookie), keeps `settings.json`, then shuts down the API server. A restart is required after this operation. This is irreversible.
{
"confirm": true
}
{
"success": true,
"message": "blockchain data purged successfully, restart required"
}
{
"error": "confirmation required (set confirm: true)"
}unauthorized{
"error": "internal error"
}unauthorized
{
"error": "invalid JSON body"
}
{
"error": "block not found"
}
{
"error": "wallet is locked"
}
{
"error": "no wallet loaded"
}
Machine-readable OpenAPI 3.1 spec available at:
api_openapi.json