I called a free API key until it died. It took exactly 50 requests.
The API key page says "1,000 credits/month" in a gray little subtitle, the kind of number you skim past and assume means "plenty." I wanted to know what it means in actual requests, so instead of reading the docs page one more time I wrote a loop.
Getting a key
No password, no card, just an email address. I used a throwaway one and had a key back in about two seconds:
curl -X POST https://toolsthatdontupload.com/api-keys/create \
-H "Content-Type: application/json" \
-d '{"email":"test@example.com"}'
# -> ttdu_free_..., 1000 credits/month

The loop
I picked a network tool, /api/dns-lookup, because network tools are the ones that actually need a key (compute tools like hashing are free and keyless). Then I called it in a plain for-loop with a fresh fake domain each time, and read X-Credits-Remaining off every response:
for (let i = 0; i < 60; i++) {
const r = await fetch("https://toolsthatdontupload.com/api/dns-lookup", {
method: "POST",
headers: { "Content-Type": "application/json", "X-API-Key": KEY },
body: JSON.stringify({ domain: `example${i}.com` })
});
console.log(i, r.status, r.headers.get("x-credits-remaining"));
}
The number dropped in a straight line, no surprises, no hidden burst allowance: 1000, 980, 960, 940... exactly 20 credits gone per call, every single time. No per-minute throttling kicked in either, even hitting it back-to-back with zero delay between calls. Whatever rate limiting the headers advertise (there's a RateLimit-Remaining field listed in the CORS-exposed headers), it didn't fire within 60 rapid calls to the same endpoint.
Call number 50
At call 49 the remaining count read 0, and the response was still a normal 200. Call 50 is where it actually stops:
HTTP/1.1 402 Payment Required
{
"title": "Usage Limit Reached",
"status": 402,
"detail": "All API credits have been used for this billing period.
Purchase additional credits or upgrade your plan to continue.",
"message": "API 사용량을 모두 소진하였습니다. 추가 크레딧을 구매하거나
플랜을 업그레이드해 주세요.",
"used": 1000,
"monthlyLimit": 1000,
"prepaid": 0,
"needed": 20
}
A couple of things stood out. It's a 402, not a 429 — this is a billing cutoff, not a rate limit, and the status code is honest about that distinction instead of reusing 429 like a lot of APIs do. The error body also ships bilingual, English and Korean in the same JSON, which matches the rest of the site, and it tells you exactly how many credits the next call would have cost (needed: 20) even though you have none left.
So, in plain numbers
- 1,000 free credits, 20 credits per network-tool call → 50 requests before you're cut off.
- Compute tools (hash, PDF merge, text/date utilities) don't touch this counter at all, since they don't need a key in the first place.
- No burst throttle visible in 60 calls with zero delay between them; the limit that actually bites is the monthly credit total, not request speed.
- Running out gets you a 402 with a clear reason and the exact cost of the next call, not a generic error.
Fifty lookups a month on a free key is obviously not going to run a production job, and it isn't meant to — it's enough to build and sanity-check an integration before deciding whether to pay. Knowing the real number up front (not the vague "plenty" I assumed before running the loop) is the difference between planning around it and getting surprised by a 402 halfway through a demo.
If you want to run the same test yourself: grab a key at /api-keys/, and the full endpoint list with example requests is in /docs/. The pricing page covers what happens after the free tier, paid plans or one-time credit packs, if 50 calls a month turns out to be too few for what you're building.