Authentication & Errors
API keys
Every request must include your API key as a Bearer token in the Authorization header.
Authorization: Bearer avn_live_YOUR_KEY
Keys are created in the Console → API Keys page. They look like avn_live_… and are shown only once on creation — copy them to a password manager immediately.
:::warning Never expose your key client-side
Don't embed avn_live_… keys in browser JavaScript or mobile app bundles. Always proxy through your backend.
:::
Key lifecycle
| Action | Where |
|---|---|
| Create a key | Console → API Keys → New key |
| Rotate a compromised key | Console → API Keys → Rotate — old key revoked immediately |
| Set an expiry | Optional, set at creation |
| Check usage | Console → API Keys → Usage tab (per-key credit breakdown) |
Error format
Every error response returns the HTTP status and a JSON body:
{ "error": "human-readable message" }
On 401, 402, and 429, the body also includes a note field with a plain-language action — surface this to your users as-is. BYOK endpoints add connect_url and signup_url:
{
"error": "byok_missing",
"note": "Connect your FRED API key to use this endpoint.",
"connect_url": "https://marketdx.app/console/integrations",
"signup_url": "https://fred.stlouisfed.org/docs/api/api_key.html"
}
Error codes
| Status | Meaning | How to fix |
|---|---|---|
400 | A parameter is malformed, out of range, or unknown. | Read the error message — it names the bad param and lists valid values. |
401 | API key missing, invalid, or revoked. | Send a valid Authorization: Bearer avn_live_… header. Create or rotate at Console → API Keys. |
402 | Out of credits (daily quota exhausted). Or for BYOK endpoints: key not connected (byok_missing) or rejected (byok_invalid). | Credits: wait for 00:00 UTC reset or upgrade. BYOK: connect the key at Console → Integrations — body carries connect_url. |
404 | No resource found with that ID or ticker. | Verify the ticker with GET /v1/stocks/resolve, or the node ID with GET /v1/megatrends. Not a server fault. |
422 | Request body is valid JSON but fails validation (wrong type, missing required field). | Check the request body shape against the endpoint schema. |
429 | Rate limit exceeded. Or for BYOK/Comtrade: third-party provider throttled us (byok_rate_limited). | Retry after the seconds in Retry-After. Comtrade free tier: ~1 req/sec. |
500 | Unexpected server error. | Retry after a short delay. If it persists, contact support with the X-Request-Id from the response header. |
503 | A BYOK third-party (e.g. UN Comtrade) is temporarily unavailable (byok_unavailable). | Retry shortly. Fall back to general knowledge meanwhile. |
Rate limits
Rate limits are enforced per API key, per minute. Every response includes:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1722441660
X-RateLimit-Reset is a Unix timestamp (UTC) for when the window resets. When you hit the limit, the 429 response adds:
Retry-After: 12
Handling 429 in code
- Python
- Node.js
import time, requests
def get_with_retry(url, headers, params=None, max_retries=3):
for attempt in range(max_retries):
r = requests.get(url, headers=headers, params=params)
if r.status_code == 429:
wait = int(r.headers.get("Retry-After", 5))
time.sleep(wait)
continue
r.raise_for_status()
return r.json()
raise Exception("Rate limit retries exhausted")
async function getWithRetry(url, headers, retries = 3) {
for (let i = 0; i < retries; i++) {
const res = await fetch(url, { headers });
if (res.status === 429) {
const wait = parseInt(res.headers.get("Retry-After") ?? "5", 10);
await new Promise(r => setTimeout(r, wait * 1000));
continue;
}
if (!res.ok) throw new Error(await res.text());
return res.json();
}
throw new Error("Rate limit retries exhausted");
}
Credits
Credits are a daily allowance reset at 00:00 UTC. They are separate from rate limits. Running out of credits returns 402. Every response reports:
X-Credits-Charged: 5
X-Credits-Remaining: 19847
| Plan | Credits / day | Requests / min |
|---|---|---|
| Free | 200 | 10 |
| Personal | 20,000 | 60 |
| Advanced | 100,000 | 120 |
| Redistribution | Unlimited | 600 |
Credit cost by endpoint type
| Endpoint type | Cost |
|---|---|
| News feeds | 1 credit per article returned — page size is your cost |
Screener POST /v1/screen | 5 credits flat per call |
| Stock prices, financials, options, positioning | 1 credit per call |
Resolver endpoints (/v1/stocks/resolve, /v1/ta/find-signal, /v1/megatrends, /v1/gics, etc.) | Free — 0 credits |
:::tip Managing news spend
limit=100 on a news endpoint costs 100 credits. Start with limit=20 while building, and raise it in production only when you know your budget.
:::
BYOK endpoints
Endpoints for FRED, World Bank, and UN Comtrade require you to connect your own provider API key at Console → Integrations. These are marked BYOK throughout this documentation.
BYOK keys are free to obtain. When a key is missing or invalid, the 402 body tells you exactly where to connect it — relay the note and connect_url to your users.
| Provider | Free? | Rate limit |
|---|---|---|
| FRED (Federal Reserve Economic Data) | Yes | 120 req/min |
| World Bank Open Data | Yes | No hard limit |
| UN Comtrade | Yes (limited) | ~100 req/day at ~1 req/sec |