Market Data API: 401 & 429 Troubleshooting
Systematically diagnose 401 authentication failures and 429 rate limits by inspecting HTTP status, business return codes, token scope, and QPS.
Core Takeaway · 30-Second Brief
Inspect both the HTTP status code and the JSON ret field to separate authentication errors (invalid, expired, or mismatched endpoint token) from rate limiting (excessive QPS). Fix auth issues immediately without retrying; handle rate limits by batching symbols, switching real-time workloads to WebSocket, and applying jittered exponential backoff.
01
Step-by-Step Diagnostic Flow
02
Symptom-to-Cause Reference
| Symptom | Most Likely Cause | Remediation |
|---|---|---|
| Every request fails immediately | Missing or mistyped token | Print token length and first/last characters to verify |
| Works locally, fails in production | Environment variable missing in deployment | Check container/CI secret injection |
| Stocks succeed, Forex fails | Endpoint prefix mismatch | Use quote-b-api for FX/metals and quote-stock-b-api for equities |
| Succeeds initially, then fails | QPS or quota limit exceeded | Throttle request rate and add exponential backoff |
| Multi-worker spikes fail together | Multiple processes sharing one token | Centralize scheduling or cache shared responses |
03
Exponential Backoff Retry Pattern
import os, random, timeimport requestsdef get_with_backoff(url: str, params: dict, retries: int = 5) -> dict: delay = 1.0 for attempt in range(retries): resp = requests.get(url, params=params, timeout=10) body = resp.json() if resp.content else {} if resp.status_code == 401 or body.get("ret") == 401: raise RuntimeError(f"Auth failed (ret=401): {body.get('msg', 'token invalid')}") if resp.ok and body.get("ret") == 200: return body if attempt == retries - 1: raise RuntimeError(f"Retries exhausted: status={resp.status_code} body={body}") time.sleep(delay + random.uniform(0, 0.5)) delay = min(delay * 2, 30) return {}if __name__ == "__main__": url = "https://quote.alltick.co/quote-stock-b-api/trade-tick" params = { "token": os.getenv("ALLTICK_API_TOKEN", "YOUR_API_TOKEN"), "query": '{"trace":"backoff-test","data":{"symbol_list":[{"code":"700.HK"}]}}', } print(get_with_backoff(url, params))04
How to Reduce Request Volume
- Batch multiple tickers into a single symbol_list request instead of polling one symbol per HTTP call.
- Migrate real-time price monitoring from high-frequency REST polling to WebSocket streaming.
- Cache responses briefly in Redis or memory when multiple downstream services read the same symbols.
- Funnel outbound API requests through a central rate limiter when running multiple worker processes.
Sources & Verification · 2026-10-13
Relevant endpoint, field, and exchange rules were checked against the primary specifications linked below.
Python examples passed ast.parse on Python 3.14.0. This checks syntax only; dependencies, runtime compatibility, and network responses were not tested.
Authenticated AllTick requests and production end-to-end tests were not run for this review. Record your token plan, library versions, market session, ret/trace, and observed results when reproducing these checks.
Primary specifications
Reproduce before deployment
- Test missing, revoked, and wrong-scope tokens; inspect HTTP status and JSON ret/msg independently. Permission and quota errors do not necessarily use HTTP 401/429.
- Coordinate limits across token-sharing workers, use bounded jittered backoff, and stop permanent authentication retries. Retain a redacted trace and timestamp.