Public API
Read-only JSON over HTTP. Broadcasting an already signed transaction is the one write.
Basics
Every node serves a public, read-only HTTP API on its public port (default 8333). Example base URL: https://lapsenode.vicnas.me, or your own node at http://host:8333.
- All amounts are integers in ticks. 1 LAPSE = 100,000,000 ticks.
- Responses are JSON. Errors return a non-2xx status with an
errorfield. - Requests are rate limited per client IP (default 60 per minute;
POST /api/tx/sendallows 20 per second). - The API sends no CORS headers, so call it from a server rather than from browser JavaScript on another origin.
- No authentication. The wallet's Send feature is only on the private local port, but broadcasting an already-signed transaction is public.
Chain
| Field | Description |
|---|---|
| height | Current chain height |
| sync_percent, sync_target | Sync progress (capped at 99 until within 3 blocks of the observed tip) and the height being synced toward |
| tip_hash, genesis_hash | Hash of the newest block and of block 0 |
| mempool_size | Pending transactions |
| peer_count | Known peers |
| address | The node's own address, or null when the operator hides it publicly (the default) |
| total_minted | Ticks minted so far (cap: 21,000,000 LAPSE) |
| burned | Ticks held by the burn address |
| circulating | total_minted minus burned |
| can_mint | Ticks still mintable before the cap |
| block_reward | Reward in ticks for the next block |
| block_time_ratio | This node's median VDF build time relative to the chain's recent median block time, or null |
| network_age_seconds | Seconds since the genesis block's timestamp |
| status | Human-readable node status |
| nick | Board nickname of the node's address, if any |
| oblivious_key | Base64 X25519 public key a client seals a request to when asking this node something through another node (see /api/oblivious), or null if the node does not take them (--no-relay) |
| public_url | The https:// address the operator says the node can also be reached at, or null (see --public-url) |
| recent_txs | Recent confirmed transactions: {height, hash, from, amount} |
curl https://lapsenode.vicnas.me/api/info
transactions list). Returns 404 with {"error": "not found"} for an unknown height.confirmations field added. Mempool transactions have confirmations: 0. Returns 404 if unknown.{"size": n, "transactions": [...]}. Each entry is {hash, from, outputs, fee}.| Field | Description |
|---|---|
| pending | Number of pending transactions |
| min, median, max | Fee rates across pending transactions (0 when the mempool is empty) |
| next_block | Suggested rate to be included in the next block. It is the lowest rate that still fit when the block is full, otherwise the relay floor of 1 tick per byte. |
Addresses
{"address": "...", "valid": true|false}. This checks format only: exactly twelve dot-separated words from the BIP39 English list. It cannot tell whether anyone holds the key.| Field | Description |
|---|---|
| address | The address queried |
| balance_ticks | Integer balance in ticks |
| balance_lapse | The same balance divided by 100,000,000 (a float, for display only) |
| Element field | Description |
|---|---|
| height | Block height containing the transaction |
| tx_hash | Transaction hash |
| direction | "sent" if the address is the sender, otherwise "received" |
| tx | The full transaction object |
Optional query parameters: limit and offset select a slice. With no limit the full history is returned. The total count is in the X-Total-Count response header.
Broadcast
{
"from": "word.word. ... (12 words)",
"pubkey": "hex FALCON-512 public key",
"outputs": [{"to": "word.word. ... (12 words)", "amount": 100000000}],
"nonce": 1,
"fee": 500,
"memo": "optional, up to 200 bytes",
"signature": "hex FALCON-512 signature"
}
Success: {"ok": true, "tx_hash": "..."}. Failure (HTTP 400): {"ok": false, "error": "reason"}, for example a bad nonce, insufficient balance or an invalid signature. The node may also answer "node busy" if its inbound queue is full.
Wallet and light clients
addr, nick, fees=1.| Field | Description |
|---|---|
| board_floor | Always present: the minimum fee a board post must pay right now |
| balance | With addr: the address's balance in ticks |
| nonce | With addr: the highest nonce the address has used, confirmed or pending. The next transaction uses this plus one. |
| nick_owner | With nick: the address that owns that board nickname, or null |
| fees | With fees=1: the same object as /api/fees |
page parameter. Returns balance, tx_count, page, total_pages and rows, each row [height, hash, direction, amount, kind] where kind is "tx" or "block" (a block the address built). Much smaller than /history, which carries whole transactions.chunks parameter is how many chunks of threads to include. The response carries an ETag: send it back as If-None-Match and an unchanged board costs a 304 with no body. Gzipped when the client sends Accept-Encoding: gzip.Peers and relay
self, peer_count, graph_peers, claims and attempting. For a plain list of ip:port strings that can seed a new node, use GET /api/peers/download, which returns a lapsecoin_peers.json file.{"nodes": ["ip:port", ...], "https": ["https://name", ...], "keys": {"ip:port": key}, "self_key": key}: this node and the peers it has found answering HTTP on its own chain, best-connected first, and the HTTPS addresses this node and those peers advertise (see --public-url), and the oblivious_key of those that take sealed requests. A short list for light clients, which cannot afford /api/peers and send a wallet address only to nodes reached over https.oblivious_key, padded to 1, 2, 4 or 8 KiB), answered sealed to the one-time key the request carries. The plaintext is {"m": method, "p": path, "b": body, "k": one-time public key}, and only /api/state, /api/fees, /api/address/{addr}/page and POST /api/tx/send are answered, by the same code as the open endpoints. It exists so a light client can name its wallet address to this node without the node that carried the request seeing the client's IP: see /api/relay and the README.{"to": "ip:port", "blob": base64}. Passes a sealed request to /api/oblivious on to, which must be a peer this node already knows answers HTTP, and returns the sealed answer. The node cannot open what it passes on. Rate limited, at most 8 KiB each way.Finding the next nonce
A transaction's nonce must be exactly one more than the sender's last used nonce, starting from 0, so the first transaction uses nonce 1. Ask /api/state?addr=...: its nonce is the highest the address has used, confirmed or pending, so the next transaction uses that plus one.