FP-004
Check your FaucetPay balance before you promise a payout
One call that stops the worst failure mode on a faucet: telling a user they were paid when the wallet was already empty.
A faucet that runs dry does not stop paying. It keeps accepting withdrawal requests, keeps calling the send endpoint, and keeps getting refusals — while the user interface says the payout succeeded.
Reading the balance before you commit turns that into an honest message. The endpoint returns the balance in the coin's smallest unit, same as everything else in the FaucetPay API.
Cache the result for a minute. A busy faucet checking the balance on every page view will spend its rate limit on nothing.
function faucetpay_balance(string $apiKey, string $currency): ?int
{
$ch = curl_init('https://faucetpay.io/api/v1/balance');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'api_key' => $apiKey,
'currency' => strtoupper($currency),
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2,
]);
$body = curl_exec($ch);
curl_close($ch);
if ($body === false) {
return null; // unknown, not zero — do not treat as empty
}
$data = json_decode((string) $body, true);
if (!is_array($data) || (int) ($data['status'] ?? 0) !== 200) {
return null;
}
return (int) $data['balance']; // smallest unit
}
function can_afford(string $apiKey, string $currency, int $units, int $reserveUnits = 0): bool
{
$balance = faucetpay_balance($apiKey, $currency);
if ($balance === null) {
return false; // cannot verify: queue it, do not send blind
}
return $balance - $reserveUnits >= $units;
}
Using it
Keep a reserve. Paying down to the last satoshi means the next automatic payout fails and lands in the manual queue anyway.
Show the balance in admin with the date it was read. An operator who can see the wallet draining will top it up before users notice.
What bites people
A failed balance check is not a zero balance. Returning 0 on error makes a network blip look like an empty wallet and stops every payout on the site.
The balance is per currency. A faucet paying five coins needs five checks, and running out of one does not mean running out of the others.
This one touches real money. Point it at a throwaway wallet and watch a full cycle before you trust it with a live balance.