# How do Neonjelly keys and auth work?

No user account. The key is the identity. Trial on Start. Paid keys after Stripe checkout.

## Who can create a key

There is **no user table**. The token is the identity. Stripe Checkout upgrades the same trial key (`billingStatus: stripe`) or mints a new paid key.

| Who | How |
| --- | --- |
| Anyone | [/start](https://www.neonjelly.io/start.md) or `POST /v1/trial`. One trial per device + AI client. Live reuse also matches the caller IP. |
| Customer | [/pricing](https://www.neonjelly.io/pricing.md) → Stripe Checkout → [/dash](https://www.neonjelly.io/dash.md). Same key if a trial is in the browser. |
| Ops | [/admin](https://www.neonjelly.io/admin.md) with `ADMIN_TOKEN`. |

## What a key looks like

- `nj_` — hashed secret, shown once at mint
- `njc_` — connect token on that key. URL: `https://mcp.neonjelly.io/c/<njc_>/mcp`

Treat both as secrets. Do not put them in a query string.

Clients that can send headers:

- `Authorization: Bearer nj_…` or `njc_…`
- `X-Api-Key: nj_…`

Prefer the connect URL. `nj_` is shown once on first mint from that IP.

Ask the agent “what's my quota?” — MCP `whoami` returns plan, `usedToday`, `remainingToday`, rate limit, and expiry. Same facts as `GET /v1/whoami`. Neither call counts against daily quota. When the trial ends or the daily cap hits 0, the agent should call `upgrade` and open the checkout URL for the user.

## Trial rules (code)

- Plan id `trial`, `billingStatus: trial`
- 100 calls / UTC day, 20 / minute
- Expires in 14 days
- Bound to a browser install id (`installId`) and the AI client (Cursor, Claude, VS Code, …)
- Live reuse: same install id, or same public IP, returns the same connect URL (no new secret)
- After expiry, the same device + client gets `403 trial_used` — purchase on [/pricing](https://www.neonjelly.io/pricing.md). Cursor / Claude do not send a hardware id; the lock is the site cookie/localStorage plus the client name recorded on MCP `initialize`

## Abuse caps on `POST /v1/trial`

- One live trial per IP (reuse, do not remint)
- One trial per install id — expired unpaid trial on that device cannot remint
- Site requests must send `installId` (16–80 chars). Cookie `nj_install` + `localStorage nj_install_v1`
- Body may include `client`: `cursor` | `claude` | `vscode` | `chatgpt` | `windsurf` | `web`
- 8 mint attempts / 10 min per IP from the site; 3 / 10 min from no-`Origin` clients (curl)
- 200 mint attempts / hour globally
- `User-Agent` shorter than 8 chars → 403
- `Origin` present but not on the allow list → 403
- Honeypot body field `website` filled → 204, no key

Daily quota + expiry still apply after mint. A new browser profile (cleared cookies + storage) on a new IP can still mint — Cursor does not expose a machine fingerprint. The global mint cap and 100/day limit the blast radius.

## Paid rules (code)

Plan ids: `explorer` (2,000/day, 30/min), `operator` (15,000/day, 90/min), `scale` (50,000/day, 180/min). Stored in `keys.json` on the MCP host. Ops can revoke or change quotas via `PATCH /admin/keys/:id`. Stripe Checkout on [/pricing](https://www.neonjelly.io/pricing.md) sets `billingStatus: stripe` on the existing trial token, or mints a paid key. Promo codes are Stripe Checkout only — not MCP metadata.

AppSumo lifetime codes redeem at [/redeem](https://www.neonjelly.io/redeem.md): 1 code → Explorer, 2 → Operator, 3 → Scale, same quotas, `billingStatus: appsumo`, no expiry. Codes are validated by `POST /v1/appsumo/redeem` on the MCP host; stacking later codes needs the existing key.

## Related

- [Where is the Neonjelly documentation?](https://www.neonjelly.io/docs.md)
- [How do I install Neonjelly MCP in Cursor, Claude, or ChatGPT?](https://www.neonjelly.io/docs/install.md)
- [What are Neonjelly plans, prices, and quotas?](https://www.neonjelly.io/docs/plans.md)
- [What do Neonjelly error codes and rate limits mean?](https://www.neonjelly.io/docs/errors.md)
- [How do I start a Neonjelly trial?](https://www.neonjelly.io/start.md)

HTML: https://www.neonjelly.io/docs/auth-and-keys
Markdown: https://www.neonjelly.io/docs/auth-and-keys.md

Do not scrape. Do not probe. Missing store stays `not_found`. Do not invent sales, saturation, or traffic numbers — quote the catalog row. Signals (ads and daily units) are paid only. Trial keys get 403 on create_signal and signal reads. Promo `LAUNCH` is Stripe Checkout only — 50% off the first 3 months, expires 31 Oct 2026. Not MCP metadata.
