API & Integration
The current public API — every endpoint listed here is live
Cast a cryptographic vote
A vote is a Bitcoin signed message. Sign the canonical vote message with the wallet that holds your registered member address, then POST the signature:
# Message to sign (exact text):
Solon vote
session:<sessionId>
choice:<yes|no|abstain>
voter:<your-bitcoin-address>
# Submit the signed vote
curl -X POST /api/sessions/<sessionId>/votes \
-H "Content-Type: application/json" \
-d '{"choice":"yes","address":"1...","signature":"<base64>"}'
The server recovers the public key from the signature and only stores the vote if it resolves to a registered member. Invalid signatures return 401; verified but ineligible votes return 422 — with the reason in both cases.
Live endpoints
Every read is public and auth-free. Open one.
- GET
/api/orgs/[slug]organization and its public member roster - GET
/api/orgs/[slug]/proposalsevery proposal with its session state - GET
/api/orgs/[slug]/auditthe append-only audit stream - GET
/api/orgs/[slug]/treasurylive on-chain treasury balances - GET
/api/orgs/[slug]/policies/[key]policy version history - GETsession, its snapshotted rules, and the live tally
/api/sessions/[sessionId] - GETself-verifying decision document — re-verify it, don't trust it
/api/v1/decisions/[sessionId] - GET
/api/healthservice health - POSTclaim a member seat by signing with a Bitcoin key
/api/members/register - POSTfile a signed proposal
/api/proposals - POSTopen the voting session and freeze the rules
/api/proposals/[proposalId]/open - POSTcast a signed vote
/api/sessions/[sessionId]/votes - POSTclose after the window and decide the outcome
/api/sessions/[sessionId]/close
All reads are public and auth-free — transparency is the product. On finalization Solon emits a decision.finalized webhook (HMAC-signed); consumers are expected to fetch the decision document and re-verify every signature locally rather than trust the notification.