API reference — index¶
Top-level navigation for the ebit-api API surface, generated against the live local stack (per CLAUDE.md, the api app on port 4000 and bo on 4003 expose Swagger).
Service map¶
| App | Local port | Stack | Live Swagger UI | OpenAPI JSON | Markdown reference |
|---|---|---|---|---|---|
api |
4000 | NestJS REST + Swagger | http://localhost:4000/swagger | http://localhost:4000/swagger.json · openapi/api.openapi.json |
api.md — 277 paths, 317 operations |
rt |
4001 | NestJS websockets (socket.io) | no Swagger — websockets only | n/a | rt-events.md |
bj |
4002 | NestJS blackjack server | no Swagger registered ¹ | n/a | orphaned per project_ebit_bj_orphan.md, no public REST surface |
bo |
4003 | NestJS backoffice | http://localhost:4003/swagger | http://localhost:4003/swagger.json · openapi/bo.openapi.json |
bo.md — 48 paths, 58 operations |
speed-roulette |
4004 | NestJS speed-roulette server | no Swagger registered ¹ | n/a | internal RPC only; events surface through rt |
¹ Verified against the running stack: curl http://localhost:{4001,4002,4004}/swagger returned 404 for all probed paths (/swagger, /api-json, /swagger.json, /swagger-json, /api/json, /api/docs). Only apps/api/src/main.ts and apps/bo/src/main.ts import buildSwagger (@app/shared/common/utils/swagger.utils); the other apps don't.
How auth works¶
All authenticated endpoints accept the same JWT in two interchangeable ways:
- Cookie:
access_token=<JWT>(HTTP-only, set byPOST /auth/sign-inandPOST /auth/refresh). This is what the public site (ebit-fe) uses end-to-end. - Authorization header:
Authorization: Bearer <JWT>(the OpenAPIbearerscheme). Easier fromcurl.
Refresh tokens live in the refresh_token cookie (and Redis-backed session).
Admin-fe legacy gotcha (per
project_admin_fe_auth_bugs.md): the admin frontend also reads/writesjwt_access_tokenfor back-compat. Both names exist in the wild; new code should useaccess_token. Seeauth-flow.mdfor the full lifecycle.
The full auth lifecycle (sign-up → sign-in → 2FA → /user/me → sign-out) is documented in auth-flow.md.
Captcha bypass (local only)¶
Endpoints guarded by RecaptchaGuard (apps/api/src/captcha/google/recaptcha.guard.ts) accept the literal token pass when the API was started with NODE_ENV=local:
The check is at apps/api/src/captcha/google/recaptcha.service.ts:28 — if (isLocal && token === 'pass') return;. The bypass is silently rejected in staging/prod (isLocal is false). See docs/audits/doppler-perf-audit.md for the full call chain.
This bypass matters for POST /auth/sign-up, POST /auth/sign-in, and a handful of payment endpoints — without it, you can't reach those endpoints from k6 or curl without solving a real reCAPTCHA challenge.
Per-app references¶
api.md— public + admin REST. Grouped by Swagger tag (Authorization API, User API, Bets API, Casino API, …). Each operation includes auth requirement, request/response schema (table form), sample curl, and a Tracing context note pointing to manual spans / blind spots fromdocs/audits/perf-trace-coverage-audit.md.bo.md— backoffice equivalent. No tracing context section (perf audit didn't coverbo).rt-events.md— websockets: handshake, auth, throttle limits, server→client and client→server event catalog.auth-flow.md— sequenced lifecycle, including thex-captcha-token: passand 2FA branches.README.md— "how to use these docs."
Regenerating the static reference¶
The local stack must be running:
# Pull fresh OpenAPI JSON
curl -s http://localhost:4000/swagger.json -o docs/api-reference/openapi/api.openapi.json
curl -s http://localhost:4003/swagger.json -o docs/api-reference/openapi/bo.openapi.json
# Re-render the Markdown
python3 docs/api-reference/_gen.py
The generator is stdlib-only — no pip install required.
Top gotchas (read before integrating)¶
- Captcha bypass is local-only and silent in prod.
x-captcha-token: passworks only whenNODE_ENV=local(apps/api/src/captcha/google/recaptcha.service.ts:28). k6 perf scripts that rely on it fail in staging without an alternate path — see../audits/doppler-perf-audit.md. - Two cookie names mean the same thing in admin-fe.
access_tokenis canonical;jwt_access_tokenis legacy (read by the admin middleware). New code usesaccess_tokenonly. Seeauth-flow.md. - socket.io auth reads the cookie, not the header.
extractSocketAuthTokenorder:auth.socket_token→ cookiesocket_token→ cookieaccess_token. SettingAuthorization: Bearer …on the upgrade request is ignored. - Bet endpoints have an OTel blind spot. The BullMQ bet-settled consumer starts an orphan trace because
traceparentisn't in the job data. See../audits/perf-trace-coverage-audit.md. - WS throttler default is 240/60s (not 120/60s).
WS_THROTTLER_LIMIT=240,WS_THROTTLER_TTL=60000inlibs/ws-throttler/src/ws-throttler.module.ts. - Authorization tag covers nine operations. Email+password sign-in plus Steam OAuth, Google OAuth, OAuth username setup, refresh, and 2FA verify all share one Swagger tag.
- Debug API is exposed on
api. 13 mutating helpers (/debug/give-balance,/debug/reset-…). Verify the guard before relying on them in tests; they should not be reachable in production.
Notes for readers¶
- The Markdown is lossy — it intentionally summarises. Live Swagger remains the source of truth for nested DTO fields, validation rules, and error response shapes.
- Operation counts (
277 paths × 317 operations) come fromopenapi/api.openapi.json— some paths expose multiple methods (e.g.GET/PATCH /user/me). - For e2e tracing demos (request → spans → Jaeger), see
../e2e-trace-demo.md. - Postman collection generated from this OpenAPI:
../api/. Refresh:docs/api/sync-postman.sh. API surface changelog:../api/changelog.md.