> ## Documentation Index
> Fetch the complete documentation index at: https://docs.0xmonaco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Testnet Faucet

> Request fake Monaco testnet assets for authenticated wallets.

The Monaco testnet faucet mints supported testnet assets to the authenticated user's wallet. It is for private alpha and testnet development only. Faucet assets have no real value.

Use the testnet faucet when a user has already connected a wallet, switched to Sei testnet, and authenticated with Monaco, but needs fake assets to test deposits, balances, spot orders, perps collateral, or app flows.

## Surface Map

| Surface | Use |
| - | - |
| REST | `POST /api/v1/faucet/mint` · `GET /api/v1/faucet/info` |
| TypeScript SDK | `sdk.faucet.mint()` · `sdk.faucet.getInfo()` |
| React SDK | Use core SDK methods through `useMonacoSDK()` |
| WebSocket | None; refresh wallet and Monaco balances after minting |
| gRPC | `FaucetService` |

<Note>
  The Monaco testnet faucet is different from the Sei gas faucet. Users still need testnet SEI in their wallet for deposit and withdrawal transactions.
</Note>

## Flow

<Steps>
  <Step title="Connect and authenticate">
    Create a Monaco session for the connected wallet. The faucet endpoint requires Monaco request signing.
  </Step>

  <Step title="Request faucet assets">
    Call the faucet once the user has access to the testnet environment. `mint()` requires a `turnstileToken` — a Cloudflare Turnstile captcha token proving the request came from a real client. Requests without a valid token are rejected.
  </Step>

  <Step title="Handle success or a thrown error">
    `mint()` resolves only when every token confirms on-chain — read `minted` for the confirmed tokens. If the mint is rate-limited, fails, partially confirms, or the faucet is unavailable, `mint()` throws instead of resolving; handle it in a `try/catch`.
  </Step>

  <Step title="Refresh balances">
    Refresh wallet balances and Monaco balances before prompting the user to deposit or trade.
  </Step>
</Steps>

## TypeScript SDK

```typescript theme={null}
await sdk.login("your-client-id");

// A valid Cloudflare Turnstile token is required on every faucet mint. Obtain
// it from the Turnstile widget rendered in your app (its success callback).
const turnstileToken = await getTurnstileToken();

try {
  const response = await sdk.faucet.mint({ turnstileToken });

  // Resolves only when every token confirmed on-chain.
  for (const token of response.minted ?? []) {
    console.log(`Minted ${token.amount} ${token.symbol}`, token.txHash);
  }

  console.log("Remaining requests:", response.remainingRequests24h);
} catch (err) {
  // 429 quota exhausted, 502 mint failed/partial (error carries the
  // minted/failed breakdown), 503 faucet unavailable (safe to retry).
  console.warn("Faucet mint did not fully succeed", err);
}
```

## REST

`POST /api/v1/faucet/mint` requires Monaco authentication headers. The request body carries a single required `turnstileToken` field (Cloudflare Turnstile captcha); requests without a valid token are rejected with HTTP 400.

```bash theme={null}
curl -X POST "https://staging.apimonaco.xyz/api/v1/faucet/mint" \
  -H "Content-Type: application/json" \
  -H "X-Monaco-PublicKey: $MONACO_SESSION_PUBLIC_KEY" \
  -H "X-Monaco-Timestamp: $MONACO_TIMESTAMP" \
  -H "X-Monaco-Signature: $MONACO_SIGNATURE" \
  -d '{"turnstileToken": "0x..."}'
```

A `200` is returned only when every token confirms on-chain — the `failed` array is empty and `remainingRequests24h` reports the remaining quota in the current 24 hour window. A `429` means the daily quota is exhausted, `502` means one or more mints failed or only partially confirmed (the error body carries the minted/failed breakdown, and delivered legs still consume the quota), and `503` means the faucet is temporarily unavailable and is safe to retry.

```json theme={null}
{
  "minted": [
    {
      "assetId": "123e4567-e89b-12d3-a456-426614174000",
      "symbol": "USDC",
      "amount": "10000.00",
      "txHash": "0x..."
    }
  ],
  "failed": [],
  "remainingRequests24h": 0
}
```

## Check quota

Call `sdk.faucet.getInfo()` (`GET /api/v1/faucet/info`, session-authenticated) to read the wallet's quota before minting — so you can show remaining requests and the next-available time instead of provoking a `429`. Quota is per wallet and app — the same wallet has its own quota on each app — and uses the same rolling-window accounting as `mint()` enforcement.

```typescript theme={null}
const info = await sdk.faucet.getInfo();

console.log(`${info.remainingRequests24h} of ${info.dailyLimit} requests left`);
if (info.remainingRequests24h === 0 && info.nextAvailableAt) {
  console.log(`Next request available at ${info.nextAvailableAt}`);
}

// Up to 5 most recent requests, newest first
for (const req of info.recentRequests) {
  console.log(req.requestedAt, req.minted.map((m) => `${m.amount} ${m.symbol}`));
}
```

Returns `remainingRequests24h`, `dailyLimit`, an optional `nextAvailableAt` (ISO 8601 — when the next request frees under the current daily limit; omitted when the rolling 24h window is empty or the limit is 0), and up to five `recentRequests` from the calling application (each with `requestedAt` and a `minted` array). Each `minted` entry is a single on-chain deposit: a faucet mint credits spot and margin separately, so one request yields a spot `USDC` entry and a margin `USDC (margin)` entry, each with its own `amount`. Each entry also carries its own `txHash`, which is optional — it is absent when that leg's transaction was submitted but never confirmed, so handle a missing hash. `nextAvailableAt` is not a fixed calendar-day reset.

## Rate Limits

The testnet faucet is rate-limited per authenticated wallet and app: the same wallet signed in to another app has its own quota there. Every mint call counts against the limit within a rolling 24 hour window (the default limit is one request). A `429` means the wallet has used its quota on this app for the current window; `getInfo()`'s `nextAvailableAt` tells you when the next request frees.

Builder UI should treat rate limits as recoverable:

* Show the user that assets may already exist in their wallet.
* Refresh wallet and Monaco balances before showing an error.
* Explain that the faucet can be tried again after the current window resets.
* Do not block the user from depositing existing testnet assets.

## Builder Checklist

* Check `window.ethereum` exists before starting wallet-authenticated faucet flows.
* Switch the wallet to Sei testnet before asking the user to sign.
* Handle `401` as an expired or missing Monaco session.
* Handle `429` as rate-limited, not as a broken wallet.
* Call `getInfo()` before `mint()` to show remaining quota and the next-available time.
* Wrap `mint()` in a `try/catch`: a resolve means every token confirmed on-chain; a throw is `429` (quota), `502` (failed/partial), or `503` (unavailable, retry).
* After faucet completion, guide the user to [Vault](/developers/vault) if they need to deposit assets into Monaco.

See [Testnet Faucet API](/api-reference/faucet/mint-all-testnet-tokens) for the generated REST schema.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.