Node API reference
The node serves two interfaces: a REST API for clients and frontends (default port 8080), and a gRPC service for node-to-node sync and gossip (default port 50051).
This surface reflects the current implementation. Treat it as current, not a frozen public API.
#REST API
#Contracts and calls
POST /deploy_contract: register a compiled contract, referencing its anchoring Bitcoin transaction.
{
"txid": "<bitcoin-txid-with-your-commitment>",
"bytecode": "<hex bytecode>",
"abi": [ ... ],
"function_offsets": { "init": 0, "transfer": 42 },
"function_offset_to_locals": { "0": 2, "42": 4 },
"constants": [ ... ],
"metadata": { }
}All fields after txid come from sclc compile --json. metadata is optional; omitted means full defaults. A deployed contract is immutable: the node refuses a second registration under the same contract ID.
POST /deploy_contract/preflight: validate an artifact and return the deploy commitment it produces, without registering anything. Compare it byte for byte with the commitment you are about to anchor.
POST /contract_call: submit a signed, anchored contract call. Body limit: 64 KB.
{
"txid": "<bitcoin-txid-of-the-anchoring-tx>",
"contract_id": "<contract-id>",
"payload": "<base64 Borsh-encoded CallEnvelope>"
}GET /contract_call/{txid}/status: execution status of a submitted call.
GET /contracts: list all known contract IDs.
#State
GET /v2/{contract_id}/{ignored}/{field}: read one field of a stored contract row. The middle segment is not used.
GET /contract_owners/{contract_id}: the outpoints that currently hold a UTXO-bound token's balances. Add ?include_pending=true to include calls not yet confirmed.
GET /fuel/{contract_id}: the contract's fuel standing: tier, stake and consumption.
GET /v2/state_root: the latest per-block state root.
GET /v2/state_root/{height}: the state root at a specific Bitcoin block height.
#Lightning channels
POST /register_channel: bind an SCL asset to a Lightning channel's funding outpoint.
GET /channels: every registered channel.
GET /channel/{txid}/{vout}: one registered channel, or null when none is registered at that outpoint.
#Events
GET /events/{contract_id}: events emitted by a contract. Optional query parameters: event_name, from_block, to_block.
Each event includes its name, decoded parameters, the emitting call's Bitcoin txid, and the confirmation block height.
#Node
GET /health: liveness check, returns 200 OK.
GET /node_status: node state summary.
#Private (require Authorization: Bearer <api_token>)
GET /calls/{contract_id}: paginated confirmed-call log. Query parameters: limit, offset.
POST /admin/clear_halt: clear a consensus halt (operator only).
#gRPC service
Defined in proto/scl.proto; used for peer sync and gossip:
| RPC | Purpose |
|---|---|
Heartbeat | Register peer activity |
SubmitPayload | Push contract payloads to a peer |
PreparePayload | Consensus prepare for validation |
GetContractIds | All known contract IDs |
GetContractSummary | State summary (Merkle root, payload hashes) |
GetContractTxids | TXIDs for a contract |
GetContractMerkleRoot | Merkle root over a contract's TXIDs |
GetPayloadByTxid | Fetch a payload by TXID |
Peers exchange Merkle summaries first and only transfer payloads that differ, so sync cost scales with divergence, not history size.