Skip to content
noxstock
Guides

Batch workflows

Run multi-symbol workflows without a bulk endpoint or quota burn.

Short answer: there is no bulk endpoint today. For batches, coverage-filter first, limit concurrency, call snapshot first, and deepen only shortlisted symbols.

Use this when

Use this for jobs like:

  • Refreshing a watchlist.
  • Scoring a list of user-entered tickers.
  • Building a nightly cache for a small symbol set.
  • Letting an agent analyze several names without calling every tool.

Do not use this for

  • Market-wide screeners. noxstock is not a full cross-symbol database today.
  • Fetching every endpoint for every symbol.
  • SEC fan-out over many heavy filers without background jobs and cache.
  • Ignoring rate limits because calls are read-only.

Route plan

REST batch plan:

# 1. Resolve names only when needed.
GET /v2/search?query=<name>

# 2. Coverage-filter the candidate symbols.
GET /v2/coverage?symbol=<symbol>

# 3. Fetch compact first-pass context for supported symbols.
GET /v2/snapshot?symbol=<symbol>

# 4. Deepen only shortlisted symbols.
GET /v2/valuation?symbol=<symbol>
GET /v2/fundamentals?symbol=<symbol>&period=quarter
GET /v2/technicals?symbol=<symbol>
GET /v2/price-action?symbol=<symbol>
GET /v2/insider?symbol=<symbol>&limit=10

For a 2–4 symbol user comparison, do not build a manual batch. Use:

GET /v2/compare?symbols=AAPL,MSFT,NVDA

For more than 4 symbols, run your own loop with concurrency control and product-side cache.

MCP sequence

MCP has no bulk tool either. Keep loops narrow:

# Per candidate:
noxstock_coverage({ "symbol": "<symbol>" })
noxstock_snapshot({ "symbol": "<symbol>" })

# Only for shortlisted symbols:
noxstock_valuation({ "symbol": "<symbol>" })
noxstock_technicals({ "symbol": "<symbol>" })
noxstock_price_action({ "symbol": "<symbol>" })

For a small basket:

noxstock_compare({ "symbols": ["AAPL", "MSFT", "NVDA"] })

What to preserve in the answer

For each symbol, preserve:

  • Coverage result: asset_type, endpoint support, and unsupported reasons.
  • Snapshot freshness, as_of, market_status, and asset_type.
  • Missing or unavailable states for any deep route.
  • Rate-limit response headers and retryable errors at the job level.
  • Calls skipped because coverage or shortlisting made them unnecessary.

For compare batches, preserve fields_requested and fields_omitted_by_symbol.

Concurrency and retry pattern

Start conservative:

  1. Normalize symbols and remove duplicates.
  2. Run coverage checks with low concurrency.
  3. Stop unsupported symbols before paid/deep calls.
  4. Fetch snapshots next.
  5. Shortlist by the facts your product needs.
  6. Call deeper routes only for the shortlist.
  7. On RATE_LIMITED, stop new work for that key and wait Retry-After when present.
  8. Resume with lower concurrency.

Plan limits matter:

PlanMinute limitBatch implication
Free30/minKeep batches small; only search, coverage, snapshot, valuation are available.
Starter60/minLimit concurrency and cache watchlists.
Builder300/minStill cache and avoid SEC fan-out.

A practical starting point is 2–5 in-flight requests per key, then tune down if X-RateLimit-Remaining falls faster than expected.

SEC routes in batch jobs

SEC-backed routes can be slow cold:

GET /v2/filings?symbol=<symbol>&form=10-K,10-Q&limit=5
GET /v2/filings/{accession}
GET /v2/filings/{accession}/section/risk_factors
GET /v2/insider?symbol=<symbol>&limit=10

Use background jobs, per-symbol loading states, and long-lived cache for filing metadata/sections. Do not fan out section text calls across a large list unless you control concurrency and have a clear user need.

Common mistakes

  • Calling /v2/fundamentals, /v2/filings, and /v2/insider for every watchlist row.
  • Treating PLAN_UPGRADE_REQUIRED as retryable during batch runs.
  • Continuing to send requests after RATE_LIMITED.
  • Retrying unsupported ETF states.
  • Dropping unavailable reasons and making all missing fields look like zero.

Next