Paid AI Behind an Anonymous Endpoint: Don't Let the Bill Teach You — Four Easy-to-Miss Holes
One night I opened my model provider's dashboard and noticed that the call-volume curve didn't match the site's traffic curve. Traffic was nearly flat. Calls were creeping up.
Nothing happened that night. It was a tiny anomaly. But I stared at that curve for a long time, asking myself: if this were real abuse, when would I find out? That night, or when the monthly bill arrived?
Then I asked the worst-case question: how much could a complete stranger make me spend in a single day? I couldn't answer it, and that was the real problem.
Anonymous AI features convert well and have a low barrier to entry, but every request behind them is real money. I already spend roughly $1,000+ a month on AI and infrastructure (that's cost, not revenue), so I can't afford not to look. Your server can't tell a person from a script, so your bill grows with call count and nothing else. Below are the four holes I found by following that question. I'm describing mechanisms and directions only, nothing anyone could follow to exploit.
Why it happens: four holes
Hole 1: An anonymous endpoint wired straight to a paid model
The most basic one: the endpoint doesn't require login and doesn't verify the requester is human. It receives a request and forwards it to a pay-per-use model.
The risk here isn't being "hacked." It's being used normally. Anyone can call it, and however many times they do, you pay.
The fix is to put a human check in front of the model call: the frontend gets a one-time token, the server verifies it, and if it fails, you spend nothing. Remember the order too: human check → rate limit → model call, never the reverse.
Hole 2: Failing open when the rate limiter errors
This one is the sneakiest, because ordinary testing never shows it.
Rate limiting usually relies on some store to count requests. The logic is typically "look up the store, reject if over the limit." But few people think hard about the other branch: what if the store query itself fails? Many implementations let the request through here, for an understandable reason: they don't want a broken limiter to lock out normal users.
The result is that rate limiting works only while the store is healthy. When the store hiccups, times out, or gets overwhelmed, the whole limiter stops working, and that is exactly when traffic is at its most abnormal.
For any endpoint wired to billing, fail closed: on error, reject. Better that some normal users see a "try again later" than that the gate swings open when the protection layer is down. I've made it a habit: whenever I review protection-layer code, I ask one separate question, when this errors, does it open or close?
Hole 3: No site-wide daily cap, and no independently capped key
Once the first two holes are patched, a structural problem remains: nothing is managing the total.
Human checks and rate limits each deal with a single requester. If requesters look different from each other, or the verification gets bypassed somehow, all those point defenses together still don't guarantee a ceiling on the site's total daily spend.
So you need two things:
- A site-wide daily cap. Once cumulative paid calls for the day hit the line, pause everything. It doesn't have to be graceful. It only has to stop the worst case.
- A separate, quota-capped key for each site and each paid feature. Don't share one across projects. If one goes wrong, it doesn't drag down the others.
Billing alerts and hard limits in the provider's dashboard belong to this layer too. One in code, one in the dashboard, both in place.
Hole 4: Preview URLs and default domains as side doors
Hosting platforms often assign extra public entry points to the same code, such as preview URLs and the platform's default domain. The protection you configured on your production domain may not cover them.
The main site looks locked down, while the entry next to it is wide open. An attacker doesn't have to break anything; they just use a different door.
The fix is straightforward: send production traffic only through domains you've bound and protected. Turn off the extra entry points, or give them equally strong protection.
A checklist you can follow
You can get through it in one evening:
- List every endpoint that is anonymously reachable and wired to billing. If it can be called without login and you pay when it's called, it's a priority.
- Add a human check before the paid model call. Fixed order: human check, rate limit, model call.
- Go through the error branches of every protection layer. When rate limiting, verification, or quota lookups fail, default to rejecting.
- Add a site-wide daily cap. Pause everything at the line, and set another layer of alerts and a hard limit in the provider's dashboard.
- Use a separate capped key for each site and each paid feature. Use it for your own testing too; don't borrow one from elsewhere.
- Audit every public entry point. Production domain, preview URLs, default domain, old domains: is the protection the same on all of them? Turn off what you don't need.
- Test the real cost with a small amount before pricing a new feature. A small amount is enough, and it beats gut feeling.
- After every change, ask again: in the worst case, how much could a stranger make me spend in a day? If you can't answer, you're not done.
I won't give thresholds, because your traffic, costs, and risk tolerance differ from mine, and a number from me would be either useless or harmful. You have to set your own.
Finally
An anonymous AI feature is essentially a customer-acquisition cost you pay yourself, and whether that cost has a ceiling decides whether it's worth building, before how useful the feature is does.
If you're still deciding whether to build this kind of feature, start with ways to monetize an indie site and work out what you can afford to pay. To see how to swap "trust" for "verify" and let automation hold your red lines, read the post on working with agents.
To follow along, subscribe to the RSS feed at /posts. I update along three lines: Agent collaboration, SEO & going global, and monetization.