Skip to main content
Two things separate a toy integration from a production one: you cache by how fast each data family actually moves, and you keep the key out of anything a user can see. Everything else (retries, quotas) links out to the page that owns it.

Keep the key server-side

The X-API-Key secret belongs in your backend, an agent runtime config, or a secret manager. Never anywhere a user or a model can read it.
  • No STOCKCONTEXT_API_KEY in a browser bundle, mobile app, public repo, prompt, log line, or screenshot.
  • Proxy client calls through your own backend; the key never reaches the browser.
  • The raw secret is shown once at creation. Store it in a secret manager, not a config file you commit. New keys come from the dashboard.
  • On suspected leak, recreate the key and swap it in. Revocation takes effect within seconds (the auth cache holds a verified key for at most 15 seconds).
  • Do not cache UNAUTHORIZED or PLAN_UPGRADE_REQUIRED responses as if they were data; a fixed key or upgrade should take effect immediately.

Cache by data family

A snapshot during market hours goes stale in seconds; a 10-K section never changes. Cache each family on its own clock. These are starting points to tune against your traffic, not API contracts:
Data familySuggested cache
Search and coverageHours to days
Snapshot during market hours30–120 seconds
Snapshot after close5–30 minutes
Valuation, fundamentals, earnings, dividends1–24 hours
Technicals, price action, history5–30 minutes for active views; longer for offline reports
Filing metadata and section textDays to indefinite
Insider activity1–24 hours
Calendar1–24 hours
Only search, coverage, snapshot, and valuation are reachable on a Free key; every other family in this table needs Starter or Builder and returns 403 PLAN_UPGRADE_REQUIRED on a Free key. See plans and limits for the route gating. Two hooks make these TTLs self-tuning. Every payload carries cache_age_seconds (0 means freshly computed), so you can see how warm the served data already was. And every response carries freshness: if it comes back stale or degraded, shorten your own TTL or show the caveat rather than caching it long.

Cache keys

Key by route plus normalized params. A snapshot key is as simple as:
nox:snapshot:AAPL
Normalize before you build the key: uppercase the symbol, sort comma-joined multi-value params (series, form, fields), and apply defaults so range=1y and an omitted range hit the same entry. A history key with sorted series looks like nox:history:AAPL:range=1y:series=close,rsi_14. The REST filings param is form (comma-joined, e.g. form=10-K,10-Q); the MCP filings_list tool calls the same argument forms (an array).
If two plans or keys can see different data or quotas, scope the key with nox:snapshot:AAPL:builder or a per-key hash. A shared cache that ignores plan scope can serve a Free-route miss as a hit, or leak one tenant’s warmer data to another.

Retries and rate limits

Wrap every call in the retry loop that honors Retry-After, caps attempts, and retries only retryable: true. The code lives in errors and retries; use it directly rather than reimplementing it here. Every authenticated response carries X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix epoch seconds); watch Remaining against Limit to back off before you hit a 429. The per-plan minute and quota numbers live on plans and limits.

SEC routes need a loading state

Filing and insider routes read from EDGAR. A cold fetch for a heavy filer can be slow, so do not block a page render on it. Run those routes in a background job or behind a loading state, and cache the result hard, because filing section text is effectively immutable.
GET /v2/filings?symbol=AAPL&form=10-K,10-Q&limit=5
GET /v2/filings/{accession}
GET /v2/filings/{accession}/section/risk_factors

Preserve the honest fields

Whatever your UI shows, carry these through from the response so the answer stays truthful:
  • freshness, as_of, market_status, and cache_age_seconds.
  • reason and available: false on unsupported families, fields_omitted_by_symbol from compare, and summary_90d.notices from insider rollups.
  • Units and signs: _usd, _pct, share counts, drawdowns, cash-flow signs, insider net values.
Hiding a stale, degraded, or unsupported state makes the number look more certain than it is. Surface it.

Batch workflows

Run many symbols with bounded concurrency and no bulk endpoint.

Plans and limits

Per-plan minute limits, monthly quotas, and route gating.