Ethora Faucet
API Docs
Programmatically request BEP-20 tokens, query wallet cooldowns, monitor faucet reserves, and receive real-time transaction events via webhooks. All responses are JSON.
Authentication
All API requests must include your API key in the request header. Keys are scoped to a specific environment (only in v1) and can be generated from your developer dashboard.
Never expose your API key in client-side JavaScript or public repositories. Use environment variables and server-side requests only.
API Key Header
X-Faucet-API-Key: ef_live_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Example Authenticated Request
curl https://api.ethora.io/v1/faucet/status \ -H "X-Faucet-API-Key: ef_live_sk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json"
API keys have the following prefix conventions: ef_live_sk_ for live keys and ef_test_sk_ for sandbox testing keys. Both operate against the BNB Smart Chain in v1.
Base URL & Versioning
All endpoints are versioned. The current stable version is v1. Breaking changes will be released under a new version prefix and the previous version will receive a 12-month deprecation window.
https://api.ethora.io/v1
| Environment | Base URL | Chain |
|---|---|---|
| testnet | https://api.ethora.io/v1 | BNB (97) |
| sandbox | https://sandbox.api.ethora.io/v1 | Mocked responses |
The sandbox mirrors the production API 1:1 but returns mocked blockchain responses without broadcasting real transactions. Ideal for integration testing and CI pipelines.
Rate Limits
Rate limits are applied per API key. All responses include X-RateLimit-* headers so you can track your current usage. Exceeding the limit returns a 429 Too Many Requests response with a Retry-After header.
| Tier | Requests / min | Drips / day | Webhook Events |
|---|---|---|---|
| Free | 30 | 10 | — |
| Basic | 120 | 100 | 3 endpoints |
| Pro | 600 | Unlimited | Unlimited |
Rate Limit Headers
X-RateLimit-Limit: 120 X-RateLimit-Remaining: 87 X-RateLimit-Reset: 1716912060 Retry-After: 34 # only present on 429 responses
POST /faucet/request
Dispatch a token drip to a specified BNB Smart Chain wallet address. This is the core endpoint — it validates the address, checks the cooldown window, verifies the Turnstile captcha token, and broadcasts a BEP-20 transfer transaction on Chain ID 97.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| wallet_address | string | Required | EVM-compatible wallet address starting with 0x, exactly 42 characters. Must be a valid checksum or lowercase hex address. |
| tokens | string[] | Required | Array of BEP-20 token symbols to send. Maximum 5 per request. Example: ["USDT", "LINK", "CAKE"]. Use GET /tokens for the full list. |
| captcha_token | string | Required | Cloudflare Turnstile token obtained client-side. Must be a valid, unexpired token issued for your registered domain. Omit only in sandbox mode. |
| note | string | Optional | Arbitrary string up to 120 characters. Stored alongside the request record, returned in GET /wallet/history. Useful for tagging automated CI runs. |
{
"wallet_address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
"tokens": ["USDT", "LINK", "CAKE"],
"captcha_token": "0.xxxxxxxxxxxxxxxxxxxxxxxx",
"note": "ci-run-#482 DEX integration test"
}
{
"success": true,
"request_id": "req_01HX9KZB4P6WQNJ3T2VQKF8MR",
"tx_hash": "0x3f9d2a1c4b0e7f8a5c6d9e2b1f3a4c7e0b9d2f5a8c1e4b7d0f3a6c9e2b5f8a",
"wallet_address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
"tokens_sent": [
{ "symbol": "USDT", "amount": "10000", "decimals": 18 },
{ "symbol": "LINK", "amount": "500", "decimals": 18 },
{ "symbol": "CAKE", "amount": "300", "decimals": 18 }
],
"fee_bnb": "0.03",
"block_number": 39874521,
"created_at": "2025-05-20T14:32:11.042Z",
"next_request_at": "2025-05-21T14:32:11.042Z"
}
{
"success": false,
"error": {
"code": "INVALID_ADDRESS",
"message": "wallet_address must be a 42-character hex string starting with 0x",
"field": "wallet_address"
}
}
{
"success": false,
"error": {
"code": "COOLDOWN_ACTIVE",
"message": "This wallet was recently funded. Please wait before requesting again.",
"next_request_at": "2025-05-21T14:32:11.042Z",
"seconds_remaining": 72941
}
}
GET /faucet/status
Returns real-time operational status of the faucet service, including current gas price on the testnet, number of pending transactions in the queue, and estimated delivery time for new requests.
No request body. No required parameters. Authentication is optional — unauthenticated calls are allowed but are rate-limited to 10 req/min.
{
"status": "operational", // "operational" | "degraded" | "down"
"queue_depth": 4,
"gas_price_gwei": "3.1",
"estimated_delivery_sec": 8,
"last_block": 39874529,
"requests_today": 47238,
"uptime_30d_pct": "99.8",
"chain_id": 97
}
GET /faucet/balance
Returns the current token reserves held by the faucet hot wallet. Useful for monitoring scripts to alert when a token is running low and needs topping up.
{
"bnb_reserve": "18.432",
"tokens": [
{ "symbol": "USDT", "balance": "42000000", "low_threshold": "500000", "is_low": false },
{ "symbol": "LINK", "balance": "180000", "low_threshold": "50000", "is_low": false },
{ "symbol": "MKR", "balance": "820", "low_threshold": "200", "is_low": false }
],
"updated_at": "2025-05-20T14:31:58.000Z"
}
GET /tokens
Returns the full list of available BEP-20 tokens including their mainnet contract addresses, drip amounts, category type, and current availability status. Use this to build dynamic token pickers in your own interfaces.
Query Parameters
| Param | Type | Required | Description |
|---|---|---|---|
| type | string | Optional | Filter by token type. One of Stablecoin, DeFi, L1 Peg, Wrapped, Oracle, Utility. |
| available_only | boolean | Optional | If true, excludes tokens marked wip: true. Defaults to false. |
{
"count": 18,
"tokens": [
{
"symbol": "USDT",
"name": "Tether USD",
"contract_address": "0x55d398326f99059fF775485246999027B3197955",
"decimals": 18,
"drip_amount": "10000",
"type": "Stablecoin",
"available": true,
"icon_url": "https://assets.coingecko.com/coins/images/325/small/Tether.png"
}
// ... more tokens
]
}
GET /tokens/:symbol
Returns detailed metadata for a single BEP-20 token by its ticker symbol. Symbol matching is case-insensitive.
curl https://api.ethora.io/v1/tokens/CAKE \ -H "X-Faucet-API-Key: ef_live_sk_xxx"
{
"symbol": "CAKE",
"name": "PancakeSwap Token",
"contract_address": "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82",
"decimals": 18,
"drip_amount": "300",
"type": "DeFi",
"available": true,
"bscscan_url": "https://bscscan.com/token/0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82",
"faucet_reserve": "2840000"
}
GET /wallet/cooldown
Check whether a wallet address is currently in its 24-hour cooldown period and how long until the next request is allowed. Does not require authentication.
| Param | Type | Required | Description |
|---|---|---|---|
| address | string | Required | The EVM wallet address to check. Must be a valid 42-character hex string. |
{
"address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
"on_cooldown": true,
"last_request_at": "2025-05-20T14:32:11.042Z",
"next_request_at": "2025-05-21T14:32:11.042Z",
"seconds_remaining": 72941
}
GET /wallet/history
Returns the paginated drip history for a specific wallet address — all past token requests with their transaction hashes, timestamps, and statuses. Useful for audit trails and dashboard UIs.
| Param | Type | Required | Description |
|---|---|---|---|
| address | string | Required | The wallet address to query history for. |
| limit | integer | Optional | Number of records per page. Default 20, max 100. |
| before | string | Optional | Cursor for pagination. Pass the cursor from the previous response to get the next page. |
{
"address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
"total": 14,
"cursor": "req_01HX2KZB1P2WQNJ3T1VQKF6MR",
"has_more": true,
"requests": [
{
"request_id": "req_01HX9KZB4P6WQNJ3T2VQKF8MR",
"tx_hash": "0x3f9d2a1c...f8a",
"tokens": ["USDT", "LINK", "CAKE"],
"status": "confirmed", // "pending" | "confirmed" | "failed"
"block_number": 39874521,
"note": "ci-run-#482 DEX integration test",
"created_at": "2025-05-20T14:32:11.042Z"
}
]
}
POST /webhooks
Register a webhook endpoint to receive real-time event notifications. When a drip transaction confirms, fails, or the faucet reserve falls below a threshold, Ethora will send a signed HTTP POST to your URL within seconds.
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Required | HTTPS endpoint to receive events. Must respond with 2xx within 10 seconds. |
| events | string[] | Required | Array of event types to subscribe to. See Webhook Events. |
| secret | string | Optional | Shared secret used to compute HMAC-SHA256 signatures. If omitted, one is generated for you and returned in the response. |
| filter_wallet | string | Optional | If provided, only events for this specific wallet address will be sent to this webhook. |
{
"url": "https://yourapp.io/webhooks/faucet",
"events": ["drip.confirmed", "drip.failed", "reserve.low"],
"filter_wallet": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
}
Webhook Events
Each event is delivered as a JSON payload with a standard envelope plus event-specific data. The full list of subscribable events:
Payload Envelope
{
"id": "evt_01HXB2MFQKR7WY9XNPJA3T8VLZ",
"type": "drip.confirmed",
"api_version": "v1",
"created_at": "2025-05-20T14:32:19.000Z",
"data": {
"request_id": "req_01HX9KZB4P6WQNJ3T2VQKF8MR",
"wallet_address": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
"tx_hash": "0x3f9d2a1c4b0e7f8a5c6d9e2b1f3a4c7e0b9d2f5a8c1e4b7d0f3a6c9e2b5f8a",
"tokens": ["USDT", "LINK", "CAKE"],
"block_number": 39874521,
"gas_used": 184320
}
}
Webhook Signature Verification
Every webhook delivery includes an X-Ethora-Signature header. This is an HMAC-SHA256 signature of the raw request body using your webhook secret. Always verify this signature before processing the payload.
const crypto = require('crypto'); function verifyWebhook(rawBody, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(rawBody) .digest('hex'); const sig = signature.replace('sha256=', ''); return crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(sig) ); }
Never compare signatures with === — this is vulnerable to timing attacks. Use crypto.timingSafeEqual (Node.js) or an equivalent constant-time comparison in your language.
Error Codes
All error responses follow a consistent structure. The error.code field contains a machine-readable string; error.message is human-readable.
Retry-After header.SDKs & Libraries
Official SDK packages are available for the most common environments. All SDKs wrap the REST API and provide typed request/response models.
npm install @ethora/faucet-sdk
import { EthoraFaucet } from '@ethora/faucet-sdk'; const faucet = new EthoraFaucet({ apiKey: process.env.ETHORA_API_KEY }); // Request tokens const result = await faucet.request({ walletAddress: '0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B', tokens: ['USDT', 'LINK'], captchaToken: turnstileToken }); console.log(result.txHash); // 0x3f9d2a... // Check cooldown const cd = await faucet.cooldown('0xAb5801...'); if (!cd.onCooldown) { console.log('Ready to request!'); }
Available Packages
| Language | Package | Status |
|---|---|---|
| JavaScript / TypeScript | @ethora/faucet-sdk | Stable |
| Python | ethora-faucet | Stable |
| Go | github.com/ethora/faucet-go | Beta |
| Rust | ethora-faucet (crates.io) | Beta |
Changelog
v1.2.0 — 2025-05-15
- Added
GET /wallet/historyendpoint with cursor-based pagination. - Webhook events now include
gas_usedfield ondrip.confirmed. - Added
filter_walletparameter to webhook registration. - TWT, SXP, ALPACA tokens added to the available list.
v1.1.0 — 2025-04-01
- Introduced webhook system with HMAC-SHA256 signature verification.
- Added sandbox environment at
sandbox.api.ethora.io. GET /faucet/balancenow returns per-tokenlow_thresholdandis_lowflags.
v1.0.0 — 2025-02-14
- Initial public API release.
- Core endpoints:
/faucet/request,/faucet/status,/tokens,/wallet/cooldown. - Cloudflare Turnstile captcha integration.