Every API product has the same conversion killer:
Landing page → "Sign up" → Email → Password → Verify →
"Check your inbox" → Create API key → Finally call the API
Six steps before the developer feels a single token of value.
We had that wall. Then I ripped it out.
The problem with signup-first
Developers don't register to read about your API. They register
to use it. But you make them commit before they can verify the
thing even works.
The result? They bounce. Your analytics show 200 visitors, 3 signups,
and you blame the landing page copy.
The copy is fine. The wall is the problem.
What I built instead
A playground. No login. No email. No password.
You land on the page, pick a model, type a prompt, hit Run.
The response comes back in 800ms. The developer sees it work.
Now they want an API key.
The economics
I was terrified this would bleed money. It didn't.
- Free trial: 10 requests/day per IP, capped at 500 tokens each
- Real cost per request: ~$0.0003 (DeepSeek pricing)
- Cost per acquired registrant: under $0.05
Compare that to Google Ads at $2-5 per click for "OpenAI API alternative."
The playground is the cheapest acquisition channel we have.
The code is boring (and that's the point
The endpoint is ~80 lines of FastAPI:
@app.post("/api/playground/chat")
async def playground_chat(request: Request):
client_ip = get_client_ip(request)
# Rate limit: 10/day per IP (in-memory, no DB)
allowed, used, limit = check_rate_limit(client_ip)
if not allowed:
return JSONResponse(429, {
"message": "Daily limit reached. Register for unlimited access.",
})
# Forward to upstream — same code path as the real API
cfg = resolve_upstream(body["model"])
resp = await client.post(
f"{cfg['base_url']}/chat/completions",
headers={"Authorization": f"Bearer {cfg['api_key']}"},
json={"model": cfg["model"], "messages": [...],
"max_tokens": 500},
)
# Return ONLY content + tokens — never the API key
return {"content": resp.json()["choices"][0]["message"]["content"],
"tokens": resp.json()["usage"]["total_tokens"]}
Key decisions:
- No auth — genuinely zero friction
- No user record — rate limit by IP in memory, no DB writes
- Token cap — 500 max, enough to feel the model, not enough to mine
- Never expose the key — the response contains only content and tokens
The part nobody talks about: CSP
Here's the bug that almost killed the launch.
The playground loads marked.js and highlight.js for Markdown rendering.
Our nginx had a strict Content-Security-Policy:
script-src 'self' 'unsafe-inline'
That blocks CDN scripts. The libraries silently failed to load.
marked was undefined. The init crashed. The model dropdown
stayed disabled. Nobody could send a message.
The fix? Self-host the libraries. Same origin = CSP compliant.
No policy change, no security trade-off.
- <script src="https://cdnjs.cloudflare.com/.../marked.min.js">
+ <script src="/js/marked.min.js">
Lesson: if your playground looks broken, check the Network tab
before the code. CSP violations don't throw visible errors —
they just... don't load.
Results
After one week:
- Playground bounce rate: 31% (vs 68% on the signup page)
- Playground → Registration conversion: 19%
- Zero abuse (the 10/day IP limit holds)
- Total cost: under $1 The signup wall was costing us developers. The playground gave them back.
The takeaway
If you build an API product, build the playground first.
Not the docs. Not the SDK. Not the blog post about your latency.
The playground. The thing where someone types words and the model
talks back. That's the demo that closes itself.
We're AIBridge — one API key, 14 Chinese AI models (DeepSeek, Qwen,
GLM, Moonshot), OpenAI-compatible. The playground is live and free:
👉 https://aibridge-api.com/playground.html
No signup required. Try it, then decide.





Top comments (0)