Different audiences
The validator’s API is for advanced users (operators, custodians, sovereignty-aware customers). The host’s API is for application developers who just want a backend.
If the validator is the chain runtime, Smart Host is the Backend-as-a-Service built on top of it. It’s the tier most application developers actually talk to: sign in with a wallet, store some data, run a function, send a message — all of it backed by the validators and, through them, the chains underneath, without making you deal with raw blockchain plumbing.
We could have built this into the validator. We didn’t, for three reasons:
Different audiences
The validator’s API is for advanced users (operators, custodians, sovereignty-aware customers). The host’s API is for application developers who just want a backend.
Different security boundaries
The host holds no chain keys, so it can grow and serve many apps without spreading key material any further.
Different scaling profile
The validator is heavy; the host is fan-out and light. Decoupling lets each scale independently.
The host holds no chain keys and signs nothing on chain. To check a wallet signature, or to get anything done on chain, it calls the validator over HTTP.
%%{init: {'flowchart':{'htmlLabels':true,'curve':'basis'}}}%%
flowchart LR
Dev([App developer]) --> Host["Smart Host"]
Host --> Auth["Auth<br/>wallet sign-in · subscription NFT check"]
Host --> DB["Database + files<br/>Merkle proofs · encrypted storage"]
Host --> Fn["Functions<br/>sandboxed serverless"]
Host --> Msg["Messaging<br/>channels · real-time stream"]
Auth -.->|verify signature| V["Smart Validator"]
DB -.->|epoch roots signed| V
Wallet-based: you prove you control an address by signing a one-time challenge. There are two sign-in flows, one for the app’s owner and one for the app’s customers.
POST /api/v3/baas/auth/challenge with { chain, walletAddress, appId }.
The host returns a challengeId, the message to sign, and when it expires.message with the wallet for walletAddress.POST /api/v3/baas/auth/verify with { challengeId, signature } (plus
publicKey where the chain needs it). The host asks the validator to check the
signature.An app’s customers sign in the same way through POST /api/v3/baas/customer-session/challenge
and POST /api/v3/baas/customer-session/verify, and get a short-lived bearer token (15
minutes at most). If the app sells subscriptions, the host checks at sign-in whether the
customer holds the app’s subscription NFT and records its tier on the session.
Sessions are kept by the host and shared with the other clusters, so a token works wherever the next request lands, and it can be ended before it expires.
Each app gets its own document database, with collections you create and query over HTTP. What makes it different is that every write is recorded in a Merkle tree.
GET /api/v3/baas/db/:appId/:collection/:documentId/proof.Files work alongside the database. Each uploaded file is encrypted with its own AES-256-GCM key and stored in the validators’ private object store. Files are not put on IPFS.
%%{init: {'flowchart':{'htmlLabels':true,'curve':'basis'}}}%%
flowchart LR
Val["document"] --> Leaf["leaf hash"]
Leaf --> Mid["intermediate hashes"]
Mid --> Root["epoch root"]
Root --> Signed["signed by a validator (ML-DSA)"]
Root -.-> Chain[("Hedera anchor<br/>not yet enabled")]
Sandboxed serverless execution. You deploy a function to the host, and the host runs it
in its own isolated V8 sandbox with a memory limit and a timeout. The code is screened
before it runs, and its outbound fetch can reach only the app’s own host and the
hosts the app declared.
Functions can be triggered by:
HTTP
Called like any API.
Schedule
Runs on a schedule, once for each of the app’s customers who opted in.
Data events
A database insert, update or delete, or a file upload or delete, fires the function.
See Host Functions for the full programming model.
Real-time pub/sub on named channels. You publish with
POST /api/v3/baas/messaging/:appId/channels/:channel/publish. To receive, you get a
single-use ticket from .../subscribe-ticket and open the channel’s stream at
.../subscribe?ticket=, which delivers messages as Server-Sent Events. Channels also keep
history and presence. Messages reach subscribers on every cluster, and the same session
token as the REST side authorises both.
Every request to the host passes the same checks: the session token is verified, the request is rate-limited by the app’s subscription tier, and its usage is metered. The metered usage is charged to the app’s subscription in HSUITE. Hosts also announce themselves to the gateways, so traffic can find them (see Smart Gateway).
%%{init: {'sequence':{'showSequenceNumbers':false}}}%%
sequenceDiagram
autonumber
participant Cl as Client (session token)
participant GW as Smart Gateway
participant H as Smart Host
participant P as Other hosts
participant V as Smart Validators
Cl->>GW: HTTPS insert
GW->>H: forward
H->>H: check session
H->>H: rate limit (subscription tier)
H->>H: write document, update Merkle tree
H-->>Cl: state transition + Merkle proof
H->>P: replicate the write
H->>V: epoch closes, request root signatures
V-->>H: ML-DSA signature over the epoch root
The host keeps your data and its proofs; a validator vouches for each epoch root.