Portal
Documentation: all sections

Sable Vault

Sable Vault is a private registry for tokenized real-world assets. The principle is tokenize privately, settle publicly: everything sensitive is sealed before it touches storage, every state change is hash-chained, and batch commitments anchor to Solana, so a public observer can verify that history is intact without learning what it contains.

What is private, what is public

SurfaceVisibility
Declared value, yield, maturity, notesSealed (AES-256-GCM), issuer's session only
Position sizesSealed, each holder sees only their own
Transfer amounts and counterpartiesSealed, the two parties only
Asset name and typeVisible to holders of the asset
Event commitments and chain hashesPublic: GET /v1/vault/chain/{id}
Batch anchor roots + Solana signaturesPublic: GET /v1/vault/anchors/{id}

The database stores sha256 commitments of the sealed content, so a leaked dump reveals structure, never values. Supporting documents are never uploaded at all: the browser hashes them locally and only the digest is registered.

The ledger

Every asset carries an append-only event chain:

hash(n) = sha256( hash(n-1) ‖ commitment(n) )

Rewriting any event breaks every later hash. The chain is public: anyone holding an asset id can fetch it and recompute every link, no Sable account required.

Settlement

The anchor worker batches unanchored event hashes, computes a batch root, and publishes sable-vault:v1:<root> to Solana mainnet as a memo transaction. GET /v1/vault/anchors/{id} returns the root, the ordered event hashes, and the Solana signature, so the root is recomputable and the on-chain memo checkable by anyone. Events not yet covered by a finalized anchor are labeled awaiting anchor: the registry never fabricates settlement.

Distributions: paying holders

Real assets pay: interest, dividends, a principal return. A distribution records a payout the issuer made across current holders, split pro-rata by position. It is not a transfer. It does not move principal; it records that a total was paid and seals each holder's share.

POST /v1/vault/assets/{id}/distribute   { total_usd, kind, note? }

kind is one of yield, interest, dividend, principal, other. The total is split pro-rata across holders by current position, floored per holder with the rounding remainder handed to the largest holder, so the shares sum to the declared total to the micro-dollar. Each share is sealed at rest; the payout appends one hash-chained yield_distribution event, so it anchors to Solana with everything else. The issuer sees the total; each holder sees only their own share (GET /v1/vault/distributions). A distribution fires an amount-free vault_distribution webhook.

Proofs: verify without revealing

An owner mints a signed statement disclosing exactly the fields they choose (POST /v1/vault/proofs). The statement carries the chain head, the latest anchor, and the disclosed values, signed secp256k1/EIP-191 by the same signer as receipts, and verifies through the same public endpoint:

curl https://api.buildsable.com/v1/receipts/verify \
-H 'content-type: application/json' \
-d '{"receipt": "<proof>", "signature": "<signature>"}'

The trust model, honestly

Every proof embeds its own trust framing: attested (signed by the Sable registry over its hash-chained ledger) plus a public anchor when one exists. This is not zero-knowledge cryptography, and we don't call it that. What a verifier gets: the registry's signature is genuine, the ledger it signed over is tamper-evident, and its anchors exist on a public chain. What a verifier is trusting: that Sable's registry recorded honestly. Asset entries are issuer-declared. The registry records what an issuer states and proves the record's integrity; it does not appraise assets or verify backing.

What Sable Vault is not

Registry infrastructure only: Sable does not custody assets, make investment offers, or provide legal enforcement of ownership. Those wrappers belong to issuers and their counsel.

Endpoints

MethodPathAuth
POST / GET/v1/vault/assetssession
GET/v1/vault/assets/{id}session
GET/v1/vault/portfoliosession
GET/v1/vault/assets/{id}/holderssession, issuer only (the cap table)
POST/v1/vault/assets/{id}/closesession, issuer only, irreversible
POST/v1/vault/assets/{id}/distributesession, issuer only (pay holders)
POST / GET/v1/vault/transferssession
GET/v1/vault/distributionssession (your payouts, as issuer or holder)
POST/v1/vault/proofssession
GET/v1/vault/chain/{id}public
GET/v1/vault/anchors/{id}public

An issuer sees the full holder register (/holders); each holder sees only their own position. Closing an asset chains an asset_closed event and stops transfers permanently, irreversible by design, so recorded history can never quietly change meaning. Transfers fire amount-free vault_transfer_sent / vault_transfer_received webhooks.

Transfers settle to another wallet's Sable account: the recipient signs in once (SIWE) before they can receive, so positions are never unclaimable.