API
Three ways to get a drip on Filecoin Calibration: a public low-limit endpoint for open-source CLIs, the captcha-gated path the web UI uses, and an API-key path for CI / test runners that need a higher cap.
Public drip no auth, no captcha
For public open-source CLIs that ship to end users and cannot embed a secret. Smaller drip, stricter per-IP cap, same per-address cap.
curl -X POST https://faucet.reiers.io/api/public/drip/fil \
-H 'content-type: application/json' \
-d '{"address":"0xYourAddressHere"}'
Same shape for USDFC:
curl -X POST https://faucet.reiers.io/api/public/drip/usdfc \
-H 'content-type: application/json' \
-d '{"address":"0xYourAddressHere"}'
Live caps and amounts are advertised on
/api/info
under publicDrip, so CLIs can render real
numbers without hardcoding. Defaults today:
- tFIL drip: 1000 tFIL per request
- USDFC drip: 100 USDFC per request
- Per-IP cap: 1 request per asset per 24h
- Per-address cap: 2 requests per asset per 24h (shared with the captcha path)
Need more than once a day? See the API key path below.
Dual-drip endpoint tFIL + USDFC in one call
A single endpoint that drips both tFIL and USDFC in one call and returns an array of per-token results. Designed for testnet wallet bootstrap flows where the caller wants both assets in one step. The envelope shape is compatible with the legacy community-faucet contract that many existing Filecoin tooling CLIs already speak, so callers can point their existing client at Plumbline with a single URL change.
curl 'https://faucet.reiers.io/api/claim_token_all?address=0xYourAddressHere'
Response:
[
{ "faucetInfo": "CalibnetFIL", "tx_hash": "0x…" },
{ "faucetInfo": "CalibnetUSDFC", "tx_hash": "0x…" }
]
Per-token errors are reported per-element, so a partial
success (e.g. FIL ok, USDFC rate-limited) still returns 200
with an error object on the failed element.
Full-failure responses return 429 with the same array shape.
Same caps as /api/public/drip/*: per-IP and per-address windows apply identically.
The response is streamed: the JSON array opens immediately
and each element is written as soon as its on-chain
transaction settles. Full dual-drip wall time is typically
60-90 seconds, so set the client request timeout to at
least 120 seconds. Use
?assets=fil or ?assets=usdfc to
drip just one token and cut wall time roughly in half.
API key for CI & test runners
Keys are issued out-of-band by the operator. Ping @Reiers on Filecoin Slack (or email [email protected]) with:
- Your name or project name
- A short description of what you'll use it for (CI, test runner, CLI, etc.)
- Expected drip volume per day
Default per-key allowance is 50 drips per asset per 24h, plenty for normal CI. Higher limits on request. Per-address limits still apply (2 per asset per 24h), so a single key can't be used to drain the faucet into one wallet.
Authenticating
Send the key as either of these headers on the drip endpoints:
Authorization: Bearer pk_yourkeyhere
X-API-Key: pk_yourkeyhere
A request that presents a valid, enabled key bypasses Cloudflare Turnstile entirely. Without a key, the drip endpoints require a Turnstile token from the web UI.
Dripping POST /api/drip/{fil,usdfc}
Body:
{
"address": "0xYourAddressHere"
}
tFIL accepts any of 0x…, t410f…,
t1…, t3…, t0….
USDFC is an ERC-20, so it only accepts 0x… or
t410f….
Example (tFIL):
curl -X POST https://faucet.reiers.io/api/drip/fil \
-H 'content-type: application/json' \
-H 'Authorization: Bearer pk_yourkeyhere' \
-d '{"address":"0xYourAddressHere"}'
Success response:
{
"ok": true,
"txHash": "0x…",
"verified": true,
"amount": "5000000000000000000",
"asset": "fil"
}
verified: true means the server confirmed
on-chain that the recipient's balance moved by at least the
drip amount before returning.
Public read endpoints
No auth required. Useful for status dashboards or monitoring.
| Method | Path | Returns |
|---|---|---|
GET | /healthz | liveness + dispenser balances |
GET | /api/info | brand, drip amounts, rate-limit defaults |
GET | /api/stats | lifetime + 24h aggregate counters |
GET | /api/recent | last N drips (default 10, max 50) |
GET | /api/convert?address=… | 0x ↔ t410f conversion via lotus RPC |
Error responses
All errors return JSON with ok: false and an
error code. HTTP status reflects the class.
| Status | Code | When |
|---|---|---|
| 400 | bad_request | Body didn't parse |
| 400 | invalid_address | Address couldn't be classified |
| 400 | usdfc_native_unsupported | USDFC drip to a t1/t3 address |
| 400 | captcha | No API key, Turnstile token missing or invalid |
| 401 | invalid_api_key | Key not recognised |
| 401 | revoked_api_key | Key disabled by the operator |
| 429 | api_key_rate_limited | Per-key drip window exhausted |
| 429 | address_rate_limited | Per-address window exhausted |
| 429 | ip_rate_limited | Per-IP window exhausted (captcha path) |
| 429 | public_ip_rate_limited | Per-IP window exhausted on /api/public/drip/* |
| 503 | faucet_dry | Dispenser balance below reserve |
| 500 | drip_failed | RPC error sending the on-chain tx |
Every 429 includes retryAtUnix (epoch seconds) so
a retry loop knows exactly when to come back:
{
"ok": false,
"error": "api_key_rate_limited",
"scope": "api_key",
"used": 50,
"max": 50,
"windowSec": 86400,
"retryAfterSec": 41832,
"retryAtUnix": 1778709058
}
More
Full reference (every endpoint, TypeScript example, shell helper for CI): docs/api.md on GitHub.
Source: github.com/Reiers/plumbline-faucet. Issues and PRs welcome.