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

# Get test USDC (sandbox only)

> Free mintable mUSDC on Base Sepolia for sandbox exploration. NOT for mainnet usage.

<Warning>
  **TESTNET / SANDBOX ONLY.** This faucet runs on **Base Sepolia (chainId 84532)**
  and hands out a mintable mock USDC (`mUSDC` at `0xD944d8e5D8329994D83950872Ec210891d3Ab6AE`).
  mUSDC has **no value on mainnet** and the mUSDC contract is not deployed there.

  **For Base mainnet (chainId 8453, LIVE since 2026-05-28), use Circle's canonical
  USDC at `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`** — acquire it via a
  bridge, an exchange, or any other standard USDC source.
</Warning>

<Note>
  Sandbox testnet only. The faucet is free, public (no signup), throttled,
  and runs on Base Sepolia (chainId 84532). It hands out a mintable mUSDC
  — see the [important footnote](#important-known-issue) below before
  attempting a real policy purchase with it.
</Note>

Two ways to claim:

* **Humans** — click the **Get test USDC** button on [lumina-org.com/faucet](https://www.lumina-org.com/faucet) and paste your wallet address.
* **Agents** — `POST` directly to the endpoint below.

## Endpoint

```
POST https://lumina-api-production-ac85.up.railway.app/api/v1/faucet/claim
Content-Type: application/json

{ "wallet": "0xYourWalletAddress" }
```

### curl

```bash theme={null}
curl -X POST https://lumina-api-production-ac85.up.railway.app/api/v1/faucet/claim \
  -H "Content-Type: application/json" \
  -d '{ "wallet": "0xYourWalletAddress" }'
```

### TypeScript (SDK)

SDK 0.6.x does **not** yet expose `lumina.faucet.claim()` — that helper is
planned for v0.7. Until then, agents should call the endpoint directly:

```ts theme={null}
const res = await fetch(
  'https://lumina-api-production-ac85.up.railway.app/api/v1/faucet/claim',
  {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ wallet: '0xYourWalletAddress' }),
  },
)
const { ethTxHash, usdcTxHash, mockUsdcAddress, nextEligibleAt } = await res.json()
```

## What you get

| Asset         | Amount     | Base units (6 dec for USDC, 18 dec for ETH) |
| ------------- | ---------- | ------------------------------------------- |
| mUSDC         | **10,000** | `10000000000`                               |
| ETH (for gas) | **0.05**   | `50000000000000000`                         |

Both arrive in the same wallet you pass, in a single faucet call, each
confirmed on Base Sepolia. The response shape is verbatim:

```jsonc theme={null}
{
  "success":          true,
  "ethTxHash":        "0x…",
  "usdcTxHash":       "0x…",
  "ethAmount":        "0.05",
  "usdcAmount":       "10000",
  "mockUsdcAddress":  "0xD944d8e5D8329994D83950872Ec210891d3Ab6AE",
  "nextEligibleAt":   "2026-05-24T18:00:00.000Z"
}
```

## Limits

| Limit               | Value                        |
| ------------------- | ---------------------------- |
| Per claim           | 10,000 mUSDC + 0.05 ETH      |
| Per wallet cooldown | **24 hours**                 |
| Per IP cooldown     | **24 hours**                 |
| Global daily cap    | **50 claims / 24h**          |
| Storage             | SQLite-backed (relayer-side) |

## Errors

Errors return `{ error, code }` with HTTP 4xx/5xx and an optional
`Retry-After` header (seconds) on rate-limit responses.

| HTTP | `code`                | Meaning                                      | Resolution                                            |
| ---- | --------------------- | -------------------------------------------- | ----------------------------------------------------- |
| 400  | `invalid_request`     | Missing or malformed `wallet` field          | Send `{ "wallet": "0x…" }` with a checksummed EOA     |
| 429  | `wallet_rate_limited` | This wallet already claimed in the last 24h  | Wait until `nextEligibleAt` or use a different wallet |
| 429  | `ip_rate_limited`     | This IP already claimed in the last 24h      | Wait or use a different network egress                |
| 429  | `daily_cap_reached`   | Global 50-claim daily cap exhausted          | Wait for UTC rollover                                 |
| 503  | `out_of_eth`          | Relayer ETH balance too low to fund 0.05 ETH | Ping the team — relayer top-up needed                 |

## Status endpoint

`GET /api/v1/faucet/status` is unauthenticated and returns:

```jsonc theme={null}
{
  "relayerEthBalance":   "0.8421",                             // ETH float, relayer wallet
  "relayerUsdcBalance":  null,                                 // null because mUSDC is mintable (no float)
  "mockUsdcAddress":     "0xD944d8e5D8329994D83950872Ec210891d3Ab6AE",
  "usdcPerClaim":        "10000",
  "ethPerClaim":         "0.05",
  "cooldownHours":       24,
  "claimsLast24h":       7,
  "dailyCap":            50,
  "enabled":             true
}
```

Use it before claiming to confirm `enabled: true` and that
`claimsLast24h < dailyCap`.

## mUSDC contract details

| Field    | Value                                                                                       |
| -------- | ------------------------------------------------------------------------------------------- |
| Address  | `0xD944d8e5D8329994D83950872Ec210891d3Ab6AE`                                                |
| Network  | Base Sepolia (84532)                                                                        |
| Decimals | **6** (same as canonical USDC)                                                              |
| Mintable | **Permissionless** — anyone can call `mint(address to, uint256 amount)` directly            |
| Explorer | [BaseScan](https://sepolia.basescan.org/address/0xD944d8e5D8329994D83950872Ec210891d3Ab6AE) |

If you'd rather skip the rate-limited faucet entirely, call `mint(to, amount)`
yourself via `cast`, `viem`, or `ethers` — there is no allowlist on the
mock contract. The faucet is only useful for clients that also need the
0.05 ETH gas top-up.

```bash theme={null}
cast send 0xD944d8e5D8329994D83950872Ec210891d3Ab6AE \
  "mint(address,uint256)" 0xYourWallet 10000000000 \
  --rpc-url https://sepolia.base.org --private-key $PK
```

## Payment token

**mUSDC (`0xD944d8e5D8329994D83950872Ec210891d3Ab6AE`) is the configured
payment token** across the protocol. `CoverRouterV2` (and `TWAPBurner`) were
reconfigured to use mUSDC, so policy purchases paid with the minted mUSDC
settle cleanly — `transferFrom(buyer, vault, premium)` succeeds. The faucet
mints this same mUSDC, so funds you receive here are exactly what the
protocol expects.

* **Use mUSDC for**: real policy purchases on Base Sepolia, SDK smoke tests, contract reads, allowance flows, tooling, monitoring integrations — every path, including the ones where CoverRouter pulls USDC.
* There is no separate bridged-USDC requirement; the legacy Circle USDC address is no longer used by the live deployment.

## Next

* **Already have an API key and want to drive policies with your own wallet?** See [Buy your first policy](/agents/first-policy).
* **Just want the fastest zero-wallet probe?** Skip the faucet entirely and go to [Sandbox-first](/agents/sandbox-first) — the relayer funds everything for you.
