Skip to content

Build1 publisher3 min readPublished

Two prices, no signup: a gate that charges every request in sats or CPU

A live demo replaces API keys, Stripe and a dashboard with one question per call: pay 10 sats or grind a SHA-256 puzzle. The arithmetic is better than the advertised timing suggests.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Illustration accompanying Two prices, no signup: a gate that charges every request in sats or CPU
Generated illustration

What happened

  • A dev.to post by zekebuilds, titled "Paywall Any API Endpoint With Two Prices: Sats or Compute", walks the scheme end to end against a live server at gate.powforge.dev, and states that every number and response shown came off a real request.
  • The post describes the usual anti-abuse fix as API keys, a signup flow, a Stripe integration, a dashboard and a support inbox for people who lost their key, and calls it a lot of plumbing to answer one question: did this caller give up something real to reach me?
  • The post frames the problem as bots hammering an endpoint a thousand times a minute, running up the operator's compute bill and giving nothing back.
  • The gate hands the caller a choice for every request: solve a SHA-256 partial collision (paying in CPU and electricity), or settle a Lightning invoice (paying in money). Both paths return the gated response.
  • A GET to https://gate.powforge.dev/api/challenge returns a fresh nonce and a difficulty; the published example returned difficulty 20.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

A developer publishing as zekebuilds has put a working per-request toll booth on the open internet at gate.powforge.dev, where every call is priced in one of two currencies: a SHA-256 proof-of-work solution, or 10 sats settled over Lightning [1][4][7]. The interesting part is not the crypto plumbing, it is the deletion: no signup, no email, no key to store, no rate-limit table to maintain [11].

The argument in the post is an operator's argument. The standard answer to scrapers hitting an endpoint a thousand times a minute is API keys, a signup flow, a Stripe integration, a dashboard, and a support inbox for people who lost their key [3][2]. All of that exists to answer one question: did this caller give up something real [2].

The mechanics are small enough to audit. A GET to /api/challenge returns a fresh nonce and a difficulty, 20 in the published example [5]. Difficulty 20 means the caller must find a string whose SHA-256, appended to the nonce, begins with 20 leading zero bits, and there is no shortcut but grinding candidates [6]. The solver is about twenty lines of Node with no dependencies [14]. Server-side verification is the same hash test run once, O(1) no matter how long the caller ground [10]. Post the solution to /api/solve and you get a token, a method field, and the gated content [9]. In a browser the loop goes in a Web Worker [12]. Callers who would rather not spin a fan take the Lightning path, which the post says speaks L402, though the material supplied cuts off mid-sentence there [13].

Now the numbers, because the headline timing is a lucky draw. The published run found a solution in 113,275 attempts and 1,277 milliseconds on one core [8]. That is roughly 88,700 hashes per second [15]. But difficulty 20 has an expected cost of 2^20, or 1,048,576 attempts [16], so that run took about nine times fewer attempts than average [17]. At the same hash rate, the mean call costs closer to 11.8 seconds of one core, not 1.3 [18].

That is bad news for the demo and good news for the defence. A million calls at the mean is about 11.8 million CPU-seconds, roughly 137 core-days [19]. The sats path prices the same volume at about $1 per thousand calls and $1,000 per million [20], and a scraper running at the thousand-a-minute rate cited in the post would be spending about $1 a minute, or $60 an hour, to keep doing it [21]. Either way the cost curve bends against the abuser and the operator's verification cost stays flat [10].

What the scheme gives up is identity. There is no caller to revoke, no quota to grant a partner, no audit trail to hand a customer who asks why their bill moved. The post shows a token coming back in the solve response but, in the material supplied, does not state its lifetime, its scope, or whether it can be replayed [22]. That is the load-bearing detail for anyone considering this in production: a per-request price that mints a reusable token is not a per-request price.

Watch for whether difficulty is tuned per caller or per route, and for the L402 half of the story, which is where refunds, retries and wallet failure modes live.

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories