HTTP API
Dusk nodes expose two main low-level HTTP surfaces:
- GraphQL for chain, block, transaction, mempool, archive, and other node-indexed queries.
- RUES-style
/on/...routes for transaction submission, contract calls, node operations, proof generation, driver management, and event subscriptions.
Use this page as an implementation guide for direct node integrations. Application code should normally use W3sper or another SDK layer unless it needs low-level node access.
You can also download the Postman collection and import it into Postman.
Base URLs
Section titled “Base URLs”- Mainnet:
https://nodes.dusk.network - Testnet:
https://testnet.nodes.dusk.network
All endpoints below are relative to one of these base URLs.
Choosing the Right Surface
Section titled “Choosing the Right Surface”Use GraphQL when you need chain, block, transaction, mempool, archive, or other node-indexed data that is not part of a contract ABI.
Use /on/contracts:<contract_id>/<method> when you are querying a method exposed by a contract ABI.
Use other /on/... routes for node operations such as transaction submission, proof generation, driver management, and event subscriptions.
Some legacy /on/... shortcut routes still work for compatibility, but are deprecated. Prefer the replacement routes documented below.
Request and Response Encoding
Section titled “Request and Response Encoding”RUES-style /on/... endpoints accept both binary and text payloads.
Request body
Section titled “Request body”- If
Content-Type: application/octet-stream, the request body is treated as raw bytes. - Otherwise, the request body is treated as UTF-8 text.
- If the text starts with
0x, the server will try to decode it as hex and treat it as bytes.
- If the text starts with
This is why most examples send serialized transactions and proofs as a 0x... hex string.
Binary responses
Section titled “Binary responses”Some endpoints return binary data. By default, binary responses are returned as hex text unless you request raw bytes:
- To force a raw binary response, set
Accept: application/octet-stream.
Version Headers
Section titled “Version Headers”Nodes include a Rusk-Version header in responses.
Clients can optionally send:
Rusk-Version: a semver requirement string, for example^1.4.0.Rusk-Version-Strict: if present, the node requiresRusk-Versionand performs a strict version check.
If the requested version is incompatible, the node rejects the request.
GraphQL Queries
Section titled “GraphQL Queries”Endpoint: /graphql
Method: POST
Body: a GraphQL-over-HTTP JSON request.
Use GraphQL for chain, block, transaction, mempool, archive, and other node-indexed data.
Query example: latest block
Section titled “Query example: latest block”curl -s -X POST "https://nodes.dusk.network/graphql" \ -H "Content-Type: application/json" \ --data-raw '{"query":"{ block(height: -1) { header { height hash } } }"}' | jq .Query example: with variables
Section titled “Query example: with variables”curl -s -X POST "https://nodes.dusk.network/graphql" \ -H "Content-Type: application/json" \ --data-raw '{ "query": "query ($height: Int!) { block(height: $height) { header { height hash } } }", "variables": { "height": -1 } }' | jq .Query example: local mempool
Section titled “Query example: local mempool”curl -s -X POST "https://nodes.dusk.network/graphql" \ -H "Content-Type: application/json" \ --data-raw '{"query":"{ mempoolTxs { id txType gasPrice gasLimit } }"}' | jq .mempoolTxs returns the node’s real local mempool in descending gas-price order. It is not a network-wide view, and it excludes future-nonce transactions temporarily staged in the node’s prequeue. See Transaction lifecycle for admission, replacement, and expiry behavior.
Legacy raw-query endpoint
Section titled “Legacy raw-query endpoint”POST /on/graphql/query is the legacy RUES GraphQL route. It accepts a raw GraphQL query string, and an empty body returns the schema SDL.
Prefer /graphql for new integrations.
curl -s -X POST "https://nodes.dusk.network/on/graphql/query" \ --data-raw 'query { block(height: -1) { header { height hash } } }' | jq .Legacy GraphQL variables can be passed through request headers using the rusk-gqlvar- prefix, for example rusk-gqlvar-height: 123.
Route Model and Deprecated Shortcuts
Section titled “Route Model and Deprecated Shortcuts”New integrations should avoid legacy shortcut routes when the same data is available through GraphQL, a contract ABI query, or contract metadata.
Current route model
Section titled “Current route model”/graphqlis the canonical GraphQL endpoint for chain, mempool, block, transaction, and archive queries./on/contracts:<contract_id>/<method>is the contract ABI query/call surface.POSTexecutes a read/query call.GETandDELETEon the same path subscribe and unsubscribe from contract events, usingRusk-Session-Id.- With
Content-Type: application/json, Rusk uses the contract data driver to encode input and decode output.
/on/contract:<contract_id>/<topic>is the contract metadata and driver-management surface.- Common topics:
metadata,download_driver, andupload_driver.
- Common topics:
/on/driver:<contract_id>/<method>is the data-driver utility surface.
Deprecated routes
Section titled “Deprecated routes”The following routes still work, but emit deprecation headers and are scheduled for removal:
/on/account:<account_bls_pk>/status/on/contract:<contract_id>/status/on/contract_owner:<contract_id>/<topic>
Deprecated responses include:
deprecation: truedeprecation-note: This endpoint is deprecated and scheduled for removal/on/contract_owner:<contract_id>/<topic> also advertises its successor:
Link: </on/contract:<contract_id>/metadata>; rel="successor-version"Migration summary
Section titled “Migration summary”| Deprecated route | Use instead | Notes |
|---|---|---|
/on/account:<account_bls_pk>/status |
POST /on/contracts:0100000000000000000000000000000000000000000000000000000000000000/account |
Returns committed balance and nonce. It does not return the old mempool-aware next_nonce. |
/on/contract:<contract_id>/status |
POST /on/contracts:0100000000000000000000000000000000000000000000000000000000000000/contract_balance |
Returns the scalar balance directly instead of { "balance": ... }. |
/on/contract_owner:<contract_id>/<topic> |
POST /on/contract:<contract_id>/metadata |
Read contract_owner from the metadata response. The legacy {topic} segment was ignored. |
The transfer genesis contract ID used for account and contract-balance queries is:
0100000000000000000000000000000000000000000000000000000000000000To inspect the transfer contract query surface directly, use its data driver schema:
curl -s -X POST \ "https://nodes.dusk.network/on/driver:0100000000000000000000000000000000000000000000000000000000000000/get_schema" | jq .Common HTTP Endpoints
Section titled “Common HTTP Endpoints”All endpoints in this section are HTTP POST calls.
- Node Info:
/on/node/info - Provisioners:
/on/node/provisioners - Common Reference String (CRS):
/on/node/crs
Example:
curl -s -X POST "https://nodes.dusk.network/on/node/info" | jq .Network
Section titled “Network”- Peers:
/on/network/peers- Request body: number of peers to return.
- Peers Location:
/on/network/peers_location
Example:
curl -s -X POST "https://nodes.dusk.network/on/network/peers" \ --data-raw '5' | jq .Gas and Fees
Section titled “Gas and Fees”- Gas Price Statistics:
/on/blocks/gas-price
Optional request body: max number of mempool transactions to consider. Defaults to all.
curl -s -X POST "https://nodes.dusk.network/on/blocks/gas-price" | jq .Transactions
Section titled “Transactions”- Preverify:
/on/transactions/preverify - Propagate:
/on/transactions/propagate - Simulate:
/on/transactions/simulate
For preverify, propagate, and simulate, send the serialized transaction as bytes, for example as a 0x... hex string.
propagate returns 202 Accepted after the node accepts the transaction for routing. This does not prove that it entered the real mempool, propagated to peers, executed successfully, or finalized. A valid future-nonce transaction can be staged outside the visible mempool while the node waits for the nonce gap to close.
Example format:
curl -s -X POST "https://nodes.dusk.network/on/transactions/preverify" \ --data-raw '0x01ec00000000000000...'Accounts
Section titled “Accounts”Deprecated shortcut
/on/account:<account_bls_pk>/status is deprecated. Use the transfer contract account query instead.
Use the transfer genesis contract to query committed account state:
Endpoint: /on/contracts:0100000000000000000000000000000000000000000000000000000000000000/account
curl -s -X POST \ "https://nodes.dusk.network/on/contracts:0100000000000000000000000000000000000000000000000000000000000000/account" \ -H "Content-Type: application/json" \ --data-raw '"<ACCOUNT_BLS_PK_BASE58>"' | jq .Response:
{ "nonce": "7", "balance": "1000"}The deprecated account shortcut also returned next_nonce. That value was derived from pending mempool transactions and has no exact one-call successor.
Use Number(nonce) + 1 only when the account has no pending transactions. A signing service must serialize nonce allocation, retain its submitted transactions, and reconcile both local mempool and committed account state before reusing a nonce.
Contracts
Section titled “Contracts”Contract ABI calls
Section titled “Contract ABI calls”To query a contract method:
Endpoint: /on/contracts:<contract_id>/<method>
Method: POST
- If you send
Content-Type: application/octet-stream, the request body is treated as raw bytes. - If you send
Content-Type: application/json, and the node has a data driver for the contract, the request body is treated as JSON input and encoded automatically.
Example format:
curl -s -X POST \ "https://nodes.dusk.network/on/contracts:<contract_id>/<method>" \ -H "Content-Type: application/json" \ --data-raw '<json-input>' | jq .Contract metadata and drivers
Section titled “Contract metadata and drivers”- Contract Metadata:
/on/contract:<contract_id>/metadata - Download Data Driver:
/on/contract:<contract_id>/download_driver - Upload Data Driver:
/on/contract:<contract_id>/upload_driver- Requires a
signheader.
- Requires a
The deprecated /on/contract_owner:<contract_id>/<topic> route has been replaced by contract metadata. Read contract_owner from the metadata response.
Example:
curl -s -X POST \ "https://nodes.dusk.network/on/contract:<contract_id>/metadata" | jq .Example response:
{ "owner": "<OWNER_BLS_PK_BASE58>", "contract_owner": "<OWNER_HEX>", "driver_available": true, "driver_signature": "<SIGNATURE_HEX_OR_NULL>", "created_at": null}Contract balance
Section titled “Contract balance”Deprecated shortcut
/on/contract:<contract_id>/status is deprecated. Use the transfer contract contract_balance query instead.
Use the transfer genesis contract to query a contract balance:
Endpoint: /on/contracts:0100000000000000000000000000000000000000000000000000000000000000/contract_balance
curl -s -X POST \ "https://nodes.dusk.network/on/contracts:0100000000000000000000000000000000000000000000000000000000000000/contract_balance" \ -H "Content-Type: application/json" \ --data-raw '"<TARGET_CONTRACT_ID_HEX>"'Replacement response:
"123456"The replacement route returns the scalar balance value directly. The deprecated route wrapped that same value as { "balance": ... }.
Data drivers
Section titled “Data drivers”Drivers allow encoding and decoding contract data.
Endpoint: /on/driver:<contract_id>/<method>
Common methods:
get_schemaget_versionencode_input_fn:<fn_name>decode_input_fn:<fn_name>decode_output_fn:<fn_name>decode_event:<event_name>
Example:
curl -s -X POST \ "https://nodes.dusk.network/on/driver:<contract_id>/get_schema" | jq .- Blob by commitment:
/on/blobs:<commitment>/commitment - Blob by hash:
/on/blobs:<hash>/hash
To retrieve a JSON sidecar instead of raw bytes, set Content-Type: application/json.
Example:
curl -s -X POST \ "https://nodes.dusk.network/on/blobs:<hash>/hash" \ -H "Content-Type: application/json" | jq .Archive-enabled nodes expose:
- Active public accounts:
/on/stats/account_count - Finalized transaction count:
/on/stats/tx_count
Example:
curl -s -X POST "https://nodes.dusk.network/on/stats/tx_count" | jq .Prover Endpoints
Section titled “Prover Endpoints”- Prove:
/on/prover/prove
Send proof input as bytes, for example as a 0x... hex string. The response is proof bytes.
curl -s -X POST "https://nodes.dusk.network/on/prover/prove" \ --data-raw '0x...' \ --output proof.binEvent Subscriptions
Section titled “Event Subscriptions”Subscriptions are a two-step process:
- Open a WebSocket connection to
wss://<node>/on. - Use the session ID from that WebSocket to
GETorDELETEsubscriptions over HTTP.
WebSocket session
Section titled “WebSocket session”Connect to:
wss://nodes.dusk.network/onThe node sends the session ID as the first WebSocket text message. Use that value in the Rusk-Session-Id header.
Event URI format
Section titled “Event URI format”/on/<component>[:<entity>]/<topic>componentandtopicare case-insensitive and normalized to lowercase.entityis optional forblocksandtransactions, which allows wildcard subscriptions.entityis required forcontracts.
Common topics:
blocks:accepted,statechange,revertedtransactions:deferred,dropped,included,removed,executedcontracts: contract-specific event topics, usually emitted event names
Examples:
- All accepted blocks:
/on/blocks/accepted - A specific block:
/on/blocks:<block_hash>/accepted - All executed transactions:
/on/transactions/executed - Contract events:
/on/contracts:<contract_id>/<event_name>
Subscribe
Section titled “Subscribe”curl -i -X GET "https://nodes.dusk.network/on/blocks/accepted" \ -H "Rusk-Session-Id: <session_id>"Unsubscribe
Section titled “Unsubscribe”curl -i -X DELETE "https://nodes.dusk.network/on/blocks/accepted" \ -H "Rusk-Session-Id: <session_id>"On success, the node returns 200 OK with an empty body. Events are delivered over the WebSocket connection.
If the session ID is missing or invalid, the node returns 424 Failed Dependency.
Event Payload Format
Section titled “Event Payload Format”Events are sent as WebSocket binary messages:
u32little-endian: length of the JSON header.- JSON header bytes, including
Content-Location. - Raw event data bytes. The format depends on the event.
If you need historical data, use an archive-enabled node and GraphQL queries such as moonlightHistory, fullMoonlightHistory, and finalizedEvents. Moonlight history is populated from finalized blocks, so it is suitable for restart-safe deposit processing without reconstructing finality from live events.