Appearance
API keys
Every external service Atlas talks to needs a credential. This page is the concrete checklist — where to sign up, what tier to pick, and the env var to set. For the architectural side (which key gates which feature, how secrets stay server-side), see Data providers and Architecture.
TIP
Set every key as an environment variable on the backend host. Never commit a real key to the repo. Never paste a key into chat, comments, or AI prompts. If a key leaks, rotate it on the provider side immediately.
Finnhub — equity quotes
What it powers: live equity quotes, instrument search, intraday OHLC, WebSocket tick stream.
- Sign up at https://finnhub.io/register.
- After verifying email, the dashboard shows a free-tier API key.
Free-tier limits:
- 60 calls/minute.
- US equities sub-second; some other exchanges 15-min delayed (Atlas surfaces a
delayedbadge accordingly). - WebSocket capped to ~50 concurrent symbol subscriptions.
When to upgrade: if your watchlist / dashboards drive >60 distinct symbols per minute, or you need realtime non-US exchanges.
EODHD — fundamentals & EOD prices
What it powers: end-of-day prices, fundamentals (P/E, EBITDA, ROIC, EPS, …), dividends, splits, analyst estimates, transcripts, filings — the entire Security dashboard.
- Sign up at https://eodhistoricaldata.com.
- Pick a plan that includes fundamentals (the cheapest paid tier covers this; the free tier is intentionally limited).
- From the dashboard, copy the API token.
- Set on the backend:
EODHD_API_KEY=<your_token> EODHD_BASE_URL=https://eodhd.com/api
Free-tier limits:
- 20 calls/day, US-only, no fundamentals — useful only for evaluating Atlas itself.
When to upgrade: essentially always. The paid tier is what makes the Security dashboard usable.
OpenSky — ADS-B aircraft
What it powers: live aircraft positions on the globe.
- Register at https://opensky-network.org/login.
- Account creation is free.
- Set on the backend:
OPENSKY_USERNAME=<your_username> OPENSKY_PASSWORD=<your_password> - Or skip: OpenSky also accepts unauthenticated requests at lower rate limits. Atlas works without these vars but with reduced refresh frequency.
Tier notes:
- Anonymous: ~10-second polling, capped daily quota.
- Authenticated: faster polling and higher quota.
- Coverage gaps over oceans and remote interiors are inherent to ADS-B itself, not OpenSky.
MarineTraffic — AIS vessels
What it powers: live vessel positions on the globe.
- Register at https://www.marinetraffic.com/en/users/register.
- The free tier does not expose API access — you need a paid Atlas-compatible plan.
- From your account, generate an API key with vessel-position scope.
- Set
MARINETRAFFIC_API_KEY=<your_key>on the backend.
If you don't set this:
- The AIS layer on the globe is empty.
- Vessel-related How-do-I recipes (e.g., Track a vessel) won't return data.
- Everything else (markets, news, ADS-B, AI chat) works normally.
Coverage notes: see Data delays & limits.
Cesium Ion — globe rendering
What it powers: the 3D globe itself — terrain, imagery, base tiles.
- Sign up at https://ion.cesium.com.
- Create a default access token. Restrict its scope to the asset IDs the globe needs — a token with full account access leaks if anyone exfiltrates the frontend bundle.
- Set both vars (the same token value in both):
CESIUM_ION_TOKEN=<your_token> # backend VITE_CESIUM_ION_TOKEN=<your_token> # frontend (PUBLIC — bundled) - Rebuild the frontend so the new
VITE_*value is bundled in.
Critical: the VITE_CESIUM_ION_TOKEN ends up world-readable. Treat it as public. Use a token scoped only to the assets the globe needs; never a root-permission token.
Free-tier limits: generous for development; production Atlas instances should monitor Ion usage and scale the token as needed.
Stripe — billing
What it powers: subscription management, paid plan gating, invoice/payment-method UX (entirely on Stripe-hosted pages).
- Sign up at https://dashboard.stripe.com/register. Use Test mode for dev, Live mode for prod.
- From Developers → API keys, copy the secret key.
- Create one Price object per plan tier (free, pro, advisory) at Products. Note each Price ID.
- From Developers → Webhooks, add a webhook to
https://<your-atlas>/webhooks/stripelistening for:checkout.session.completed,customer.subscription.updated,customer.subscription.deleted,invoice.payment_failed,invoice.payment_succeeded. Copy the signing secret. - Set on the backend:
STRIPE_SECRET_KEY=<sk_live_… or sk_test_…> STRIPE_WEBHOOK_SECRET=<whsec_…> STRIPE_PRICE_ID_FREE=<price_…> STRIPE_PRICE_ID_PRO=<price_…> STRIPE_PRICE_ID_ADVISORY=<price_…>
Skip if: you're running Atlas free of charge or self-hosting for a single team. Without these vars, all users default to free-tier feature flags. See Self-hosting.
Required vs optional summary
| Provider | Required? | Without it… |
|---|---|---|
| Finnhub | Yes | Market panel and watchlist quote streams empty |
| EODHD | Yes | Security dashboard empty; fundamentals view empty |
| Cesium Ion | Yes | Globe doesn't render |
| OpenSky | Optional (recommended) | ADS-B layer empty (or anonymous mode at lower limits) |
| MarineTraffic | Optional | AIS layer empty |
| Stripe | Optional | All users on free tier |
Rotation and revocation
- On schedule: every 90 days for production-critical providers.
- On suspected leak: immediately. Rotate on the provider, deploy the new value, restart the backend.
- Atlas's
_key()helper (in service modules) re-readsos.environon every call — no app restart strictly required for backend-only keys, but a restart is the safe default. - Cesium Ion frontend token rotation requires a frontend rebuild + redeploy because the token is bundled.
Verifying
After setting keys, restart the backend and hit /health (see backend/routes/health.py) — the response includes per-provider readiness when configured.
For a live test:
- Finnhub: load any popular ticker (e.g., AAPL) in the Market panel — quote should populate.
- EODHD: open Security dashboard on the same ticker — fundamentals should populate.
- Cesium Ion: load
/and confirm the globe renders terrain. - OpenSky / MarineTraffic: enable the respective layer and confirm pins appear over a covered region.