DEV Community

Daniel Dong
Daniel Dong

Posted on

I killed our signup wall. Registrations went up.

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
Enter fullscreen mode Exit fullscreen mode

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.

playground

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"]}
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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">
Enter fullscreen mode Exit fullscreen mode

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.

1

3

4

5

Top comments (0)