Chapter 3 — API & backend services¶
Guided time: 5–7 hours
Prerequisites: Chapter 2 — Environment
Next: Chapter 4 — Engine
1. Purpose¶
The HTTP layer is what operators and dashboards see first. Understanding it separates “the server is up” from “the strategy is sane.” This chapter focuses on render_api.py as the primary app, how CORS and static assets fit a Netlify-style frontend, and how to probe routes safely with FastAPI TestClient.
2. Objectives¶
- Describe responsibilities of
render_api.pyat a high level. - Explain when to read
api/app.pyinstead (legacy / parallel features / tests). - Use
TestClientfor repeatable local checks without manual curl. - Identify read-only vs mutating routes before you call them against real keys.
3. render_api.py — how to read a large FastAPI file¶
Large apps accumulate routes. Use a systematic approach:
- App construction —
FastAPI(...), middleware, global state. - Startup —
on_event("startup")or lifespan hooks (depending on FastAPI version in your branch). - Auth — JWT, bearer tokens,
/auth/tokenpatterns if present. - Core trading / portfolio —
/status,/positions,/trades,/signals. - ML / analytics —
/ml/status,/ml/performance, etc. - Sentiment / quantum —
/sentiment,/quantum/analysis. - Admin / reports — report generators, logs, toggles.
Teaching trick: assign each student one vertical slice (e.g. “all /ml/* routes”) and have them diagram data sources.
4. api/app.py vs render_api.py¶
Reasons a repository keeps two apps:
- Historical evolution —
api/app.pymay predate the unified Render-oriented file. - Test fixtures — some tests import
api.app:appdirectly. - Feature divergence — one path may include experimental admin routes.
Rule of thumb for new work: follow whatever the root README names as official (render_api.py today). If you merge apps, do it deliberately with a migration note.
5. Routers and modularity¶
api/routes_grid.py demonstrates APIRouter: mount related endpoints under a prefix in the main app (exact prefix depends on your include_router call—verify in render_api.py or api/app.py).
Why routers matter: they let you document and test cross-pair grid logic without scrolling a 2k-line file.
6. CORS¶
Browser-based dashboards on another origin (e.g. Netlify) require CORS headers. You will see CORSMiddleware with permissive settings in development-oriented configs.
Production hardening (your responsibility when you deploy):
- Restrict
allow_originsto your real frontend hostnames. - Review
allow_credentialsand cookie/JWT patterns.
This course does not prescribe your final CORS policy—only that you know it exists.
7. TestClient mini-course¶
Minimal health test¶
from fastapi.testclient import TestClient
import render_api
client = TestClient(render_api.app)
response = client.get("/health")
assert response.status_code == 200
body = response.json()
assert isinstance(body, dict)
Why TestClient beats curl in teaching¶
- Assertions in code become regression tests later.
- Students practice Python, not only shell one-liners.
Caveat¶
Some routes assume background tasks, websockets, or global singletons initialized at startup. TestClient may not perfectly mirror production unless you trigger startup events—read FastAPI docs for lifespan / startup in your version.
8. Route inventory lab¶
Run a search:
rg "@app\\.(get|post|put|delete)" render_api.py
Pick five routes:
| Route | GET/POST | Suspected read/write | Needs auth? |
|---|---|---|---|
| … | … | … | … |
Fill the table from reading docstrings and function bodies.
9. Example routes (verify in your tree)¶
Your checkout may include paths similar to:
/health— liveness / feature flags/status— richer dashboard payload/signals— strategy outputs/trades//trades/recent— history views/sentiment— sentiment snapshot/ml/status— model health metrics/quantum/analysis— quantum-inspired analytics/trading/start,/trading/stop— control endpoints
Never assume semantics without reading the handler—names drift.
10. Security mindset¶
Before you point a browser at a public tunnel (ngrok, etc.):
- Keys live server-side only.
- Disable trading until intentional.
- Rate-limit aggressive polling endpoints in your frontend.
Chapter 7 expands operational security.
11. Labs¶
Lab 3.1 — TestClient script (45 min)¶
Create labs/api_probe.py (gitignore labs/ if needed) that:
- GET
/health - GET
/api-infoif present - Prints keys of JSON responses (sorted)
Lab 3.2 — Error handling (30 min)¶
Call a route that requires missing credentials or data. Capture status code and body shape; document in markdown.
Lab 3.3 — Router trace (45 min)¶
Find where routes_grid router is included. Diagram full URL path clients must use.
12. Exercises¶
- Why might
allow_origins=["*"]be acceptable in class but risky in production? - Name one route that returns P&L or equity-related fields (read the handler to confirm).
13. Notebook¶
notebooks/01_testclient_tour.ipynb — cells for each probe; markdown interpretation under each cell.
14. Summary¶
You can now navigate the HTTP layer deliberately. The engine chapter explains what happens after a signal is requested or a bar is injected—two different entry patterns that converge in operations.
Next: Chapter 4 — Engine