Faucet (testnet HSUITE)
To do almost anything on the testnet — mint a subscription, deploy a Smart App — your wallet needs some HST. The faucet dispenses it. It’s the one surface you can call before you have a subscription: a public, wallet-authenticated bootstrap path.
How it works
Section titled “How it works”The faucet uses a challenge → sign → dispense flow (the same ownership proof as Web3 auth), so only the wallet that controls the address can claim to it.
sequenceDiagram
autonumber
participant You as Your wallet
participant F as Faucet
participant XRPL as XRP Ledger
You->>F: requestChallenge(chain, recipientAddress)
F-->>You: { challengeId, message, expiresInSeconds }
You->>You: sign(message) with the recipient key
You->>F: dispense({ challengeId, signature, publicKey })
alt trustline_required
F-->>You: trustLine { currency, issuer, limit }
You->>XRPL: set HST trust line, then re-request a fresh challenge
else rate_limited
F-->>You: retryAfterSeconds
else faucet cannot pay
F-->>You: HTTP 503 { reason }
else dispensed
F->>XRPL: send HST
F-->>You: { amount, txHash, remainingDailyAllowance }
end
The result is a discriminated union on status:
status |
Meaning | What to do |
|---|---|---|
dispensed |
HST was sent on-chain | Done — txHash confirms it; remainingDailyAllowance is what’s left today |
trustline_required |
The recipient has no HST trust line yet | Set the returned trustLine on your wallet, then request a fresh challenge and dispense again |
rate_limited |
Daily limit hit | Wait retryAfterSeconds and retry |
How much you get
Section titled “How much you get”The faucet doesn’t drip a fixed constant — it sizes each payout to cover a real first subscription: the cheapest tier’s deposit priced at the live HSUITE/USD rate, plus one marketplace listing fee, plus a safety margin (and never below a configured floor). Because the amount is derived from the same quote the subscribe path prices with, a tier-price or exchange-rate move can’t silently leave you with too little HST to subscribe. The current per-wallet daily cap is reported as dailyCap by the status endpoint.
When the faucet itself cannot pay
Section titled “When the faucet itself cannot pay”The faucet pays from its own HST balance, and it will only drip an amount it can prove covers a first subscription. When it can’t — the balance can’t cover a payout (a testnet whose faucet hasn’t been funded yet, or has run dry), or it can’t price/size the drip right now — POST /faucet/hsuite answers HTTP 503 before any signing starts and before any of your daily allowance is used — it is not a status result. The body is the standard error envelope plus a machine-readable reason:
{ "statusCode": 503, "message": "The HSUITE faucet is out of funds and cannot pay out right now. Nothing was sent. …", "code": "DEPENDENCY_UNAVAILABLE", "domain": "dependency", "retryable": true, "timestamp": "2026-11-14T12:00:00.000Z", "path": "/api/v3/faucet/hsuite", "method": "POST", "error": "DEPENDENCY_UNAVAILABLE", "isRetryable": true, "reason": "faucet_unfunded"}reason |
Meaning | What to do |
|---|---|---|
faucet_unfunded |
The faucet holds less HST than one payout needs | Retry later, with a fresh challenge |
faucet_balance_unavailable |
The faucet could not confirm its balance, so it refused rather than guess | Retry shortly, with a fresh challenge |
faucet_quote_unavailable |
The faucet could not price a first subscription right now (no live HSUITE/USD rate), so it refused rather than under-drip | Retry shortly, with a fresh challenge |
faucet_drip_exceeds_cap |
A first subscription now needs more HST than the faucet’s per-request limit allows | A network configuration issue — report it; a retry won’t help until it is fixed |
This check comes before trustline_required and rate_limited: while the faucet can’t pay, a wallet that still lacks a trust line (or already drew today) gets the 503 instead, so nobody is asked to spend an XRP reserve on a trust line for nothing.
In the SDK this is an SdkHttpError with statusCode === 503; the body above is err.details.
The SDK exposes the faucet as FaucetClient. /api/v3/faucet/* is reachable through the public gateway (unlike the retired validator raw tier — SDK 8.0), so FaucetClient is a small standalone client you point at the gateway directly with createHttpClient:
import { FaucetClient, createHttpClient } from '@hsuite/smart-engines-sdk';
const http = createHttpClient({ baseUrl: 'https://gateway.testnet.hsuite.network/api/v3' });const faucet = new FaucetClient(http);
// 1. Request a challenge for the wallet you want fundedconst challenge = await faucet.requestChallenge('xrpl', wallet.address);
// 2. Sign the challenge message with that wallet's keyconst signature = await sign(challenge.message);
// 3. Dispenselet result = await faucet.dispense({ chain: 'xrpl', recipientAddress: wallet.address, challengeId: challenge.challengeId, signature, publicKey: wallet.publicKey,});
if (result.status === 'trustline_required') { await setTrustLine(result.trustLine); // set on the recipient wallet const fresh = await faucet.requestChallenge('xrpl', wallet.address); result = await faucet.dispense({ chain: 'xrpl', recipientAddress: wallet.address, challengeId: fresh.challengeId, signature: await sign(fresh.message), publicKey: wallet.publicKey, });}
if (result.status === 'dispensed') { console.log(`got ${result.amount} HST — ${result.txHash}`);}Check today’s allowance without dispensing:
const status = await faucet.getStatus('xrpl', wallet.address);// { dailyCap, dispensedToday, nextResetUtc }// dailyCap is the live, derived drip size (what one claim funds today)The fastest path — the CLI handles the challenge, signing, the trust line, and the retry for you:
hsuite faucet # drip HST to the wallet in .env.local (sets HST trustline if needed)hsuite init funds a new wallet with test XRP from the XRPL test network’s own faucet, not with HST. Run hsuite faucet afterwards to get HST. See CLI.
HTTP endpoints
Section titled “HTTP endpoints”Public bootstrap routes (no subscription / bearer token required — ownership is proven by the signature):
| Method | Path | Body / Query |
|---|---|---|
POST |
/api/v3/faucet/hsuite/challenge |
{ chain, recipientAddress } |
POST |
/api/v3/faucet/hsuite |
{ chain, recipientAddress, challengeId, signature, publicKey? } |
GET |
/api/v3/faucet/hsuite/status |
?chain=&recipientAddress= |
Testnet only chain must be xrpl (HST lives on XRPL).